@ -19,7 +19,6 @@ import (
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing"
folderalpha1 "github.com/grafana/grafana/pkg/apis/folder/v0alpha1"
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/infra/slugify"
internalfolders "github.com/grafana/grafana/pkg/registry/apis/folders"
@ -33,6 +32,7 @@ import (
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/guardian"
"github.com/grafana/grafana/pkg/services/libraryelements/model"
ngstore "github.com/grafana/grafana/pkg/services/ngalert/store"
"github.com/grafana/grafana/pkg/services/search"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util"
@ -645,7 +645,7 @@ type folderK8sHandler struct {
// #TODO check if it makes more sense to move this to FolderAPIBuilder
accesscontrolService accesscontrol . Service
userService user . Service
kvstore * kvstore . NamespacedKVS tore
ngAlertSvc ngstore . DBs tore
}
//-----------------------------------------------------------------------------------------
@ -653,13 +653,14 @@ type folderK8sHandler struct {
//-----------------------------------------------------------------------------------------
func newFolderK8sHandler ( hs * HTTPServer ) * folderK8sHandler {
return & folderK8sHandler {
gvr : folderalpha1 . FolderResourceInfo . GroupVersionResource ( ) ,
namespacer : request . GetNamespaceMapper ( hs . Cfg ) ,
clientConfigProvider : hs . clientConfigProvider ,
accesscontrolService : hs . accesscontrolService ,
userService : hs . userService ,
kvstore : kvstore . WithNamespace ( hs . kvStore , 0 , "storage.dualwriting" ) ,
ngAlertSvc : hs . ngAlertSvc ,
}
}
@ -780,16 +781,11 @@ func (fk8s *folderK8sHandler) deleteFolder(c *contextmodel.ReqContext) {
ctx := c . Req . Context ( )
hasDependants , err := hasDependants ( ctx , fk8s . kvstore )
err := fk8s . checkForAlertRules ( )
if err != nil {
fk8s . writeError ( c , err )
return
}
if hasDependants {
fk8s . writeError ( c , folder . ErrFolderNotEmpty . Errorf ( "this folder is not empty. Please make sure it does not contain any dashboards, alerts, library panels or SLOs" ) )
return
}
if err := client . Delete ( ctx , uid , v1 . DeleteOptions { } ) ; err != nil {
fk8s . writeError ( c , err )
return
@ -838,40 +834,6 @@ func (fk8s *folderK8sHandler) updateFolder(c *contextmodel.ReqContext) {
// Utility functions
//-----------------------------------------------------------------------------------------
func hasDependants ( ctx context . Context , kvstore * kvstore . NamespacedKVStore ) ( bool , error ) {
// TODO: how can we check for alert rules and library panels?
var folderDependants = [ ] string {
folderalpha1 . RESOURCEGROUP ,
"dashboards.dashboard.grafana.app" ,
"librarypanels.librarypanel.grafana.app" ,
"alertrules.alertmanager.grafana.app" ,
}
var hasDependants bool
for _ , resource := range folderDependants {
item , found , err := kvstore . Get ( ctx , resource )
if err != nil {
return false , err
}
if found {
mode , err := strconv . Atoi ( item )
if err != nil {
return false , err
}
// if dual writer mode > 2, it means the source of truth is unified store
if mode > 2 {
// call unified store count
fmt . Println ( "counting dependants in unified store" )
}
// if not found or mode < 3 call legacy store count
} else {
fmt . Println ( "counting dependants in legacy store" )
}
}
// TODO: also check for SLORules in another store
return hasDependants , nil
}
func ( fk8s * folderK8sHandler ) getClient ( c * contextmodel . ReqContext ) ( dynamic . ResourceInterface , bool ) {
dyn , err := dynamic . NewForConfig ( fk8s . clientConfigProvider . GetDirectRestConfig ( c ) )
if err != nil {
@ -1037,7 +999,7 @@ func (fk8s *folderK8sHandler) getFolderACMetadata(c *contextmodel.ReqContext, f
return nil , nil
}
folderIDs , err := fk8s . getParents ( f )
folderIDs , err := getParents ( f )
if err != nil {
return nil , err
}
@ -1053,7 +1015,11 @@ func (fk8s *folderK8sHandler) getFolderACMetadata(c *contextmodel.ReqContext, f
return metadata , nil
}
func ( fk8s * folderK8sHandler ) getParents ( f * folder . Folder ) ( map [ string ] bool , error ) {
func ( fk8s * folderK8sHandler ) checkForAlertRules ( ) error {
return folder . ErrFolderNotEmpty . Errorf ( "folder contains alert rules, please delete them first." )
}
func getParents ( f * folder . Folder ) ( map [ string ] bool , error ) {
folderIDs := map [ string ] bool { f . UID : true }
if ( f . UID == accesscontrol . GeneralFolderUID ) || ( f . UID == folder . SharedWithMeFolderUID ) {
return folderIDs , nil