K8s: Implement playlist api with k8s client (#77405)
This commit is contained in:
+1
-8
@@ -499,14 +499,7 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
})
|
||||
|
||||
// Playlist
|
||||
apiRoute.Group("/playlists", func(playlistRoute routing.RouteRegister) {
|
||||
playlistRoute.Get("/", routing.Wrap(hs.SearchPlaylists))
|
||||
playlistRoute.Get("/:uid", hs.ValidateOrgPlaylist, routing.Wrap(hs.GetPlaylist))
|
||||
playlistRoute.Get("/:uid/items", hs.ValidateOrgPlaylist, routing.Wrap(hs.GetPlaylistItems))
|
||||
playlistRoute.Delete("/:uid", reqEditorRole, hs.ValidateOrgPlaylist, routing.Wrap(hs.DeletePlaylist))
|
||||
playlistRoute.Put("/:uid", reqEditorRole, hs.ValidateOrgPlaylist, routing.Wrap(hs.UpdatePlaylist))
|
||||
playlistRoute.Post("/", reqEditorRole, routing.Wrap(hs.CreatePlaylist))
|
||||
})
|
||||
hs.registerPlaylistAPI(apiRoute)
|
||||
|
||||
// Search
|
||||
apiRoute.Get("/search/sorting", routing.Wrap(hs.ListSortOptions))
|
||||
|
||||
@@ -16,6 +16,8 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/avatar"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
httpstatic "github.com/grafana/grafana/pkg/api/static"
|
||||
@@ -205,6 +207,7 @@ type HTTPServer struct {
|
||||
authnService authn.Service
|
||||
starApi *starApi.API
|
||||
promRegister prometheus.Registerer
|
||||
clientConfigProvider grafanaapiserver.DirectRestConfigProvider
|
||||
}
|
||||
|
||||
type ServerOptions struct {
|
||||
@@ -246,8 +249,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
|
||||
accesscontrolService accesscontrol.Service, navTreeService navtree.Service,
|
||||
annotationRepo annotations.Repository, tagService tag.Service, searchv2HTTPService searchV2.SearchHTTPService, oauthTokenService oauthtoken.OAuthTokenService,
|
||||
statsService stats.Service, authnService authn.Service, pluginsCDNService *pluginscdn.Service,
|
||||
starApi *starApi.API, promRegister prometheus.Registerer,
|
||||
|
||||
starApi *starApi.API, promRegister prometheus.Registerer, clientConfigProvider grafanaapiserver.DirectRestConfigProvider,
|
||||
) (*HTTPServer, error) {
|
||||
web.Env = cfg.Env
|
||||
m := web.New()
|
||||
@@ -348,6 +350,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
|
||||
pluginsCDNService: pluginsCDNService,
|
||||
starApi: starApi,
|
||||
promRegister: promRegister,
|
||||
clientConfigProvider: clientConfigProvider,
|
||||
}
|
||||
if hs.Listener != nil {
|
||||
hs.log.Debug("Using provided listener")
|
||||
|
||||
+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