wip: basic logic to check that datasource exists in validation
This commit is contained in:
@@ -3,18 +3,23 @@ package collections
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
collections "github.com/grafana/grafana/apps/collections/pkg/apis/collections/v1alpha1"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/builder"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
var _ builder.APIGroupValidation = (*DatasourceStacksValidator)(nil)
|
||||
|
||||
type DatasourceStacksValidator struct{}
|
||||
type DatasourceStacksValidator struct {
|
||||
restConfigProvider apiserver.RestConfigProvider
|
||||
}
|
||||
|
||||
func GetDatasourceStacksValidator() builder.APIGroupValidation {
|
||||
return &DatasourceStacksValidator{}
|
||||
func GetDatasourceStacksValidator(restConfigProvider apiserver.RestConfigProvider) builder.APIGroupValidation {
|
||||
return &DatasourceStacksValidator{restConfigProvider: restConfigProvider}
|
||||
}
|
||||
|
||||
func (v *DatasourceStacksValidator) Validate(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
||||
@@ -54,13 +59,54 @@ func (v *DatasourceStacksValidator) Validate(ctx context.Context, a admission.At
|
||||
modes := cast.Spec.Modes
|
||||
|
||||
for _, mode := range modes {
|
||||
for key := range mode.Definition {
|
||||
for key, item := range mode.Definition {
|
||||
// if a key is not in the template, return an error
|
||||
if _, ok := template[key]; !ok {
|
||||
return fmt.Errorf("key '%s' is not in the DataSourceStack template (%s %s)", key, a.GetName(), a.GetKind().GroupVersion().String())
|
||||
}
|
||||
|
||||
exists, err := v.checkDatasourceExists(ctx, template[key].Group, item.DataSourceRef)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetching: datasource '%s' does not exist (%s %s): %w", item.DataSourceRef, a.GetName(), a.GetKind().GroupVersion().String(), err)
|
||||
}
|
||||
if !exists {
|
||||
return fmt.Errorf("datasource '%s' does not exist (%s %s)", item.DataSourceRef, a.GetName(), a.GetKind().GroupVersion().String())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *DatasourceStacksValidator) checkDatasourceExists(ctx context.Context, group, name string) (bool, error) {
|
||||
cfg, err := v.restConfigProvider.GetRestConfig(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
client, err := kubernetes.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
result := client.RESTClient().Get().
|
||||
Prefix("apis", group, "v0alpha1").
|
||||
Namespace("default").
|
||||
Resource("datasources").
|
||||
Name(name).
|
||||
Do(ctx)
|
||||
|
||||
if err = result.Error(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var statusCode int
|
||||
|
||||
result = result.StatusCode(&statusCode)
|
||||
if statusCode == http.StatusNotFound {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/collections/legacy"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/preferences/utils"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/builder"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
@@ -50,6 +51,7 @@ func RegisterAPIService(
|
||||
stars star.Service,
|
||||
users user.Service,
|
||||
apiregistration builder.APIRegistrar,
|
||||
restConfigProvider apiserver.RestConfigProvider,
|
||||
) *APIBuilder {
|
||||
// Requires development settings and clearly experimental
|
||||
//nolint:staticcheck // not yet migrated to OpenFeature
|
||||
@@ -59,7 +61,7 @@ func RegisterAPIService(
|
||||
|
||||
sql := legacy.NewLegacySQL(legacysql.NewDatabaseProvider(db))
|
||||
builder := &APIBuilder{
|
||||
datasourceStacksValidator: GetDatasourceStacksValidator(),
|
||||
datasourceStacksValidator: GetDatasourceStacksValidator(restConfigProvider),
|
||||
authorizer: &utils.AuthorizeFromName{
|
||||
Resource: map[string][]utils.ResourceOwner{
|
||||
"stars": {utils.UserResourceOwner},
|
||||
|
||||
Generated
+2
-2
@@ -886,7 +886,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api
|
||||
}
|
||||
userStorageAPIBuilder := userstorage.RegisterAPIService(featureToggles, apiserverService, registerer)
|
||||
apiBuilder := preferences.RegisterAPIService(cfg, featureToggles, sqlStore, prefService, userService, apiserverService)
|
||||
collectionsAPIBuilder := collections.RegisterAPIService(cfg, featureToggles, sqlStore, starService, userService, apiserverService)
|
||||
collectionsAPIBuilder := collections.RegisterAPIService(cfg, featureToggles, sqlStore, starService, userService, apiserverService, eventualRestConfigProvider)
|
||||
webhookExtraBuilder := webhooks.ProvideWebhooksWithImages(cfg, renderingService, resourceClient, eventualRestConfigProvider, registerer)
|
||||
v3 := extras.ProvideProvisioningExtraAPIs(webhookExtraBuilder)
|
||||
pullRequestWorker := pullrequest.ProvidePullRequestWorker(cfg, renderingService, resourceClient, eventualRestConfigProvider, registerer)
|
||||
@@ -1540,7 +1540,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
|
||||
}
|
||||
userStorageAPIBuilder := userstorage.RegisterAPIService(featureToggles, apiserverService, registerer)
|
||||
apiBuilder := preferences.RegisterAPIService(cfg, featureToggles, sqlStore, prefService, userService, apiserverService)
|
||||
collectionsAPIBuilder := collections.RegisterAPIService(cfg, featureToggles, sqlStore, starService, userService, apiserverService)
|
||||
collectionsAPIBuilder := collections.RegisterAPIService(cfg, featureToggles, sqlStore, starService, userService, apiserverService, eventualRestConfigProvider)
|
||||
webhookExtraBuilder := webhooks.ProvideWebhooksWithImages(cfg, renderingService, resourceClient, eventualRestConfigProvider, registerer)
|
||||
v3 := extras.ProvideProvisioningExtraAPIs(webhookExtraBuilder)
|
||||
pullRequestWorker := pullrequest.ProvidePullRequestWorker(cfg, renderingService, resourceClient, eventualRestConfigProvider, registerer)
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package client
|
||||
|
||||
// import (
|
||||
// "context"
|
||||
// "encoding/json"
|
||||
|
||||
// "github.com/grafana/grafana/pkg/services/apiserver"
|
||||
// "github.com/grafana/grafana/pkg/services/apiserver/client"
|
||||
// v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
// "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
// "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// )
|
||||
|
||||
// // K8sClientFactory creates a K8sClient for the given group
|
||||
// type K8sClientFactory func(ctx context.Context, group string, version string) client.K8sHandler
|
||||
|
||||
// type K8sHandler struct {
|
||||
// client.K8sHandler
|
||||
// restConfigProvider apiserver.RestConfigProvider
|
||||
// gvr schema.GroupVersionResource
|
||||
// }
|
||||
|
||||
// type K8sClient struct {
|
||||
// client.K8sHandler
|
||||
// newClientFunc K8sClientFactory
|
||||
// }
|
||||
|
||||
// func ProvideK8sClient(
|
||||
// restConfigProvider apiserver.RestConfigProvider,
|
||||
// ) K8sHandler {
|
||||
// return NewK8sClient(restConfigProvider)
|
||||
// }
|
||||
|
||||
// func NewK8sClient(restConfigProvider apiserver.RestConfigProvider) *K8sClient {
|
||||
// newClientFunc := newK8sClientFactory(restConfigProvider)
|
||||
// return &K8sClient{
|
||||
// K8sHandler: newClientFunc(context.Background(),),
|
||||
// }
|
||||
// }
|
||||
|
||||
// func (c K8sHandler) Get(ctx context.Context, name string, orgID int64, options v1.GetOptions, subresource ...string) (*unstructured.Unstructured, error) {
|
||||
// cfg, err := c.restConfigProvider.GetRestConfig(ctx)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// client, err := kubernetes.NewForConfig(cfg)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// result := client.RESTClient().Get().
|
||||
// Prefix("apis", c.gvr.Group, c.gvr.Version).
|
||||
// Namespace(string(orgID)).
|
||||
// Resource(c.gvr.Resource).
|
||||
// Name(name).
|
||||
// Do(ctx)
|
||||
|
||||
// if err = result.Error(); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// body, err := result.Raw()
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// value := &unstructured.Unstructured{}
|
||||
// if err = json.Unmarshal(body, value); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// return value, nil
|
||||
// }
|
||||
|
||||
// func newK8sClientFactory(restConfigProvider apiserver.RestConfigProvider) K8sClientFactory {
|
||||
// return func(ctx context.Context, group string, version string) client.K8sHandler {
|
||||
// gvr := schema.GroupVersionResource{
|
||||
// Group: group,
|
||||
// Version: version,
|
||||
// Resource: "datasources",
|
||||
// }
|
||||
|
||||
// return K8sHandler{
|
||||
// restConfigProvider: restConfigProvider,
|
||||
// gvr: gvr,
|
||||
// }
|
||||
|
||||
// }
|
||||
// }
|
||||
Reference in New Issue
Block a user