K8s: Implement playlist api with k8s client (#77405)
This commit is contained in:
+131
-1
@@ -2,15 +2,145 @@ package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/apis/playlist/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/endpoints/request"
|
||||
"github.com/grafana/grafana/pkg/services/playlist"
|
||||
"github.com/grafana/grafana/pkg/util/errutil/errhttp"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
func (hs *HTTPServer) ValidateOrgPlaylist(c *contextmodel.ReqContext) {
|
||||
type playlistAPIHandler struct {
|
||||
SearchPlaylists []web.Handler
|
||||
GetPlaylist []web.Handler
|
||||
GetPlaylistItems []web.Handler
|
||||
DeletePlaylist []web.Handler
|
||||
UpdatePlaylist []web.Handler
|
||||
CreatePlaylist []web.Handler
|
||||
}
|
||||
|
||||
func chainHandlers(h ...web.Handler) []web.Handler {
|
||||
return h
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) registerPlaylistAPI(apiRoute routing.RouteRegister) {
|
||||
handler := playlistAPIHandler{
|
||||
SearchPlaylists: chainHandlers(routing.Wrap(hs.SearchPlaylists)),
|
||||
GetPlaylist: chainHandlers(hs.validateOrgPlaylist, routing.Wrap(hs.GetPlaylist)),
|
||||
GetPlaylistItems: chainHandlers(hs.validateOrgPlaylist, routing.Wrap(hs.GetPlaylistItems)),
|
||||
DeletePlaylist: chainHandlers(middleware.ReqEditorRole, hs.validateOrgPlaylist, routing.Wrap(hs.DeletePlaylist)),
|
||||
UpdatePlaylist: chainHandlers(middleware.ReqEditorRole, hs.validateOrgPlaylist, routing.Wrap(hs.UpdatePlaylist)),
|
||||
CreatePlaylist: chainHandlers(middleware.ReqEditorRole, routing.Wrap(hs.CreatePlaylist)),
|
||||
}
|
||||
|
||||
// Alternative implementations for k8s
|
||||
if hs.Features.IsEnabled(featuremgmt.FlagKubernetesPlaylistsAPI) {
|
||||
namespacer := request.GetNamespaceMapper(hs.Cfg)
|
||||
gvr := schema.GroupVersionResource{
|
||||
Group: v0alpha1.GroupName,
|
||||
Version: v0alpha1.VersionID,
|
||||
Resource: "playlists",
|
||||
}
|
||||
|
||||
clientGetter := func(c *contextmodel.ReqContext) (dynamic.ResourceInterface, bool) {
|
||||
dyn, err := dynamic.NewForConfig(hs.clientConfigProvider.GetDirectRestConfig(c))
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, "client", err)
|
||||
return nil, false
|
||||
}
|
||||
return dyn.Resource(gvr).Namespace(namespacer(c.OrgID)), true
|
||||
}
|
||||
|
||||
errorWriter := func(c *contextmodel.ReqContext, err error) {
|
||||
//nolint:errorlint
|
||||
statusError, ok := err.(*errors.StatusError)
|
||||
if ok {
|
||||
c.JsonApiErr(int(statusError.Status().Code),
|
||||
statusError.Status().Message, err)
|
||||
return
|
||||
}
|
||||
errhttp.Write(c.Req.Context(), err, c.Resp)
|
||||
}
|
||||
|
||||
handler.SearchPlaylists = []web.Handler{func(c *contextmodel.ReqContext) {
|
||||
client, ok := clientGetter(c)
|
||||
if !ok {
|
||||
return // error is already sent
|
||||
}
|
||||
out, err := client.List(c.Req.Context(), v1.ListOptions{})
|
||||
if err != nil {
|
||||
errorWriter(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
query := strings.ToUpper(c.Query("query"))
|
||||
playlists := []playlist.Playlist{}
|
||||
for _, item := range out.Items {
|
||||
p := v0alpha1.UnstructuredToLegacyPlaylist(item)
|
||||
if p == nil {
|
||||
continue
|
||||
}
|
||||
if query != "" && !strings.Contains(strings.ToUpper(p.Name), query) {
|
||||
continue // query filter
|
||||
}
|
||||
playlists = append(playlists, *p)
|
||||
}
|
||||
c.JSON(http.StatusOK, playlists)
|
||||
}}
|
||||
|
||||
handler.GetPlaylist = []web.Handler{func(c *contextmodel.ReqContext) {
|
||||
client, ok := clientGetter(c)
|
||||
if !ok {
|
||||
return // error is already sent
|
||||
}
|
||||
uid := web.Params(c.Req)[":uid"]
|
||||
out, err := client.Get(c.Req.Context(), uid, v1.GetOptions{})
|
||||
if err != nil {
|
||||
errorWriter(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, v0alpha1.UnstructuredToLegacyPlaylistDTO(*out))
|
||||
}}
|
||||
|
||||
handler.GetPlaylistItems = []web.Handler{func(c *contextmodel.ReqContext) {
|
||||
client, ok := clientGetter(c)
|
||||
if !ok {
|
||||
return // error is already sent
|
||||
}
|
||||
uid := web.Params(c.Req)[":uid"]
|
||||
out, err := client.Get(c.Req.Context(), uid, v1.GetOptions{})
|
||||
if err != nil {
|
||||
errorWriter(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, v0alpha1.UnstructuredToLegacyPlaylistDTO(*out).Items)
|
||||
}}
|
||||
}
|
||||
|
||||
// Register the actual handlers
|
||||
apiRoute.Group("/playlists", func(playlistRoute routing.RouteRegister) {
|
||||
playlistRoute.Get("/", handler.SearchPlaylists...)
|
||||
playlistRoute.Get("/:uid", handler.GetPlaylist...)
|
||||
playlistRoute.Get("/:uid/items", handler.GetPlaylistItems...)
|
||||
playlistRoute.Delete("/:uid", handler.DeletePlaylist...)
|
||||
playlistRoute.Put("/:uid", handler.UpdatePlaylist...)
|
||||
playlistRoute.Post("/", handler.CreatePlaylist...)
|
||||
})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) validateOrgPlaylist(c *contextmodel.ReqContext) {
|
||||
uid := web.Params(c.Req)[":uid"]
|
||||
query := playlist.GetPlaylistByUidQuery{UID: uid, OrgId: c.SignedInUser.GetOrgID()}
|
||||
p, err := hs.playlistService.GetWithoutItems(c.Req.Context(), &query)
|
||||
|
||||
Reference in New Issue
Block a user