|
|
|
@@ -30,7 +30,7 @@ import (
|
|
|
|
|
|
|
|
|
|
provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1"
|
|
|
|
|
"github.com/grafana/grafana/apps/provisioning/pkg/auth"
|
|
|
|
|
connectionvalidation "github.com/grafana/grafana/apps/provisioning/pkg/connection"
|
|
|
|
|
"github.com/grafana/grafana/apps/provisioning/pkg/connection"
|
|
|
|
|
appcontroller "github.com/grafana/grafana/apps/provisioning/pkg/controller"
|
|
|
|
|
clientset "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned"
|
|
|
|
|
client "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1"
|
|
|
|
@@ -105,20 +105,21 @@ type APIBuilder struct {
|
|
|
|
|
jobs.Queue
|
|
|
|
|
jobs.Store
|
|
|
|
|
}
|
|
|
|
|
jobHistoryConfig *JobHistoryConfig
|
|
|
|
|
jobHistoryLoki *jobs.LokiJobHistory
|
|
|
|
|
resourceLister resources.ResourceLister
|
|
|
|
|
dashboardAccess legacy.MigrationDashboardAccessor
|
|
|
|
|
unified resource.ResourceClient
|
|
|
|
|
repoFactory repository.Factory
|
|
|
|
|
client client.ProvisioningV0alpha1Interface
|
|
|
|
|
access auth.AccessChecker
|
|
|
|
|
accessWithAdmin auth.AccessChecker
|
|
|
|
|
accessWithEditor auth.AccessChecker
|
|
|
|
|
accessWithViewer auth.AccessChecker
|
|
|
|
|
statusPatcher *appcontroller.RepositoryStatusPatcher
|
|
|
|
|
healthChecker *controller.HealthChecker
|
|
|
|
|
validator repository.RepositoryValidator
|
|
|
|
|
jobHistoryConfig *JobHistoryConfig
|
|
|
|
|
jobHistoryLoki *jobs.LokiJobHistory
|
|
|
|
|
resourceLister resources.ResourceLister
|
|
|
|
|
dashboardAccess legacy.MigrationDashboardAccessor
|
|
|
|
|
unified resource.ResourceClient
|
|
|
|
|
repoFactory repository.Factory
|
|
|
|
|
connectionFactory connection.Factory
|
|
|
|
|
client client.ProvisioningV0alpha1Interface
|
|
|
|
|
access auth.AccessChecker
|
|
|
|
|
accessWithAdmin auth.AccessChecker
|
|
|
|
|
accessWithEditor auth.AccessChecker
|
|
|
|
|
accessWithViewer auth.AccessChecker
|
|
|
|
|
statusPatcher *appcontroller.RepositoryStatusPatcher
|
|
|
|
|
healthChecker *controller.HealthChecker
|
|
|
|
|
repoValidator repository.RepositoryValidator
|
|
|
|
|
// Extras provides additional functionality to the API.
|
|
|
|
|
extras []Extra
|
|
|
|
|
extraWorkers []jobs.Worker
|
|
|
|
@@ -133,6 +134,7 @@ type APIBuilder struct {
|
|
|
|
|
func NewAPIBuilder(
|
|
|
|
|
onlyApiServer bool,
|
|
|
|
|
repoFactory repository.Factory,
|
|
|
|
|
connectionFactory connection.Factory,
|
|
|
|
|
features featuremgmt.FeatureToggles,
|
|
|
|
|
unified resource.ResourceClient,
|
|
|
|
|
configProvider apiserver.RestConfigProvider,
|
|
|
|
@@ -176,6 +178,7 @@ func NewAPIBuilder(
|
|
|
|
|
usageStats: usageStats,
|
|
|
|
|
features: features,
|
|
|
|
|
repoFactory: repoFactory,
|
|
|
|
|
connectionFactory: connectionFactory,
|
|
|
|
|
clients: clients,
|
|
|
|
|
parsers: parsers,
|
|
|
|
|
repositoryResources: resources.NewRepositoryResourcesFactory(parsers, clients, resourceLister),
|
|
|
|
@@ -192,7 +195,7 @@ func NewAPIBuilder(
|
|
|
|
|
allowedTargets: allowedTargets,
|
|
|
|
|
allowImageRendering: allowImageRendering,
|
|
|
|
|
registry: registry,
|
|
|
|
|
validator: repository.NewValidator(minSyncInterval, allowedTargets, allowImageRendering),
|
|
|
|
|
repoValidator: repository.NewValidator(minSyncInterval, allowedTargets, allowImageRendering),
|
|
|
|
|
useExclusivelyAccessCheckerForAuthz: useExclusivelyAccessCheckerForAuthz,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -253,6 +256,7 @@ func RegisterAPIService(
|
|
|
|
|
extraBuilders []ExtraBuilder,
|
|
|
|
|
extraWorkers []jobs.Worker,
|
|
|
|
|
repoFactory repository.Factory,
|
|
|
|
|
connectionFactory connection.Factory,
|
|
|
|
|
) (*APIBuilder, error) {
|
|
|
|
|
//nolint:staticcheck // not yet migrated to OpenFeature
|
|
|
|
|
if !features.IsEnabledGlobally(featuremgmt.FlagProvisioning) {
|
|
|
|
@@ -271,6 +275,7 @@ func RegisterAPIService(
|
|
|
|
|
builder := NewAPIBuilder(
|
|
|
|
|
cfg.DisableControllers,
|
|
|
|
|
repoFactory,
|
|
|
|
|
connectionFactory,
|
|
|
|
|
features,
|
|
|
|
|
client,
|
|
|
|
|
configProvider,
|
|
|
|
@@ -641,7 +646,7 @@ func (b *APIBuilder) UpdateAPIGroupInfo(apiGroupInfo *genericapiserver.APIGroupI
|
|
|
|
|
storage[provisioning.ConnectionResourceInfo.StoragePath("repositories")] = NewConnectionRepositoriesConnector()
|
|
|
|
|
|
|
|
|
|
// TODO: Add some logic so that the connectors can registered themselves and we don't have logic all over the place
|
|
|
|
|
storage[provisioning.RepositoryResourceInfo.StoragePath("test")] = NewTestConnector(b, repository.NewRepositoryTesterWithExistingChecker(repository.NewSimpleRepositoryTester(b.validator), b.VerifyAgainstExistingRepositories))
|
|
|
|
|
storage[provisioning.RepositoryResourceInfo.StoragePath("test")] = NewTestConnector(b, repository.NewRepositoryTesterWithExistingChecker(repository.NewSimpleRepositoryTester(b.repoValidator), b.VerifyAgainstExistingRepositories))
|
|
|
|
|
storage[provisioning.RepositoryResourceInfo.StoragePath("files")] = NewFilesConnector(b, b.parsers, b.clients, b.accessWithAdmin)
|
|
|
|
|
storage[provisioning.RepositoryResourceInfo.StoragePath("refs")] = NewRefsConnector(b)
|
|
|
|
|
storage[provisioning.RepositoryResourceInfo.StoragePath("resources")] = &listConnector{
|
|
|
|
@@ -682,10 +687,15 @@ func (b *APIBuilder) Mutate(ctx context.Context, a admission.Attributes, o admis
|
|
|
|
|
if ok {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
// TODO: complete this as part of https://github.com/grafana/git-ui-sync-project/issues/700
|
|
|
|
|
|
|
|
|
|
c, ok := obj.(*provisioning.Connection)
|
|
|
|
|
if ok {
|
|
|
|
|
return connectionvalidation.MutateConnection(c)
|
|
|
|
|
conn, err := b.asConnection(ctx, c, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return conn.Mutate(ctx)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r, ok := obj.(*provisioning.Repository)
|
|
|
|
@@ -736,9 +746,15 @@ func (b *APIBuilder) Validate(ctx context.Context, a admission.Attributes, o adm
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
connection, ok := obj.(*provisioning.Connection)
|
|
|
|
|
// Validate connections
|
|
|
|
|
c, ok := obj.(*provisioning.Connection)
|
|
|
|
|
if ok {
|
|
|
|
|
return connectionvalidation.ValidateConnection(connection)
|
|
|
|
|
conn, err := b.asConnection(ctx, c, a.GetOldObject())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return conn.Validate(ctx)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Validate Jobs
|
|
|
|
@@ -758,7 +774,7 @@ func (b *APIBuilder) Validate(ctx context.Context, a admission.Attributes, o adm
|
|
|
|
|
// the only time to add configuration checks here is if you need to compare
|
|
|
|
|
// the incoming change to the current configuration
|
|
|
|
|
isCreate := a.GetOperation() == admission.Create
|
|
|
|
|
list := b.validator.ValidateRepository(repo, isCreate)
|
|
|
|
|
list := b.repoValidator.ValidateRepository(repo, isCreate)
|
|
|
|
|
cfg := repo.Config()
|
|
|
|
|
|
|
|
|
|
if a.GetOperation() == admission.Update {
|
|
|
|
@@ -831,7 +847,7 @@ func (b *APIBuilder) GetPostStartHooks() (map[string]genericapiserver.PostStartH
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b.statusPatcher = appcontroller.NewRepositoryStatusPatcher(b.GetClient())
|
|
|
|
|
b.healthChecker = controller.NewHealthChecker(b.statusPatcher, b.registry, repository.NewSimpleRepositoryTester(b.validator))
|
|
|
|
|
b.healthChecker = controller.NewHealthChecker(b.statusPatcher, b.registry, repository.NewSimpleRepositoryTester(b.repoValidator))
|
|
|
|
|
|
|
|
|
|
// if running solely CRUD, skip the rest of the setup
|
|
|
|
|
if b.onlyApiServer {
|
|
|
|
@@ -1449,6 +1465,35 @@ func (b *APIBuilder) asRepository(ctx context.Context, obj runtime.Object, old r
|
|
|
|
|
return b.repoFactory.Build(ctx, r)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *APIBuilder) asConnection(ctx context.Context, obj runtime.Object, old runtime.Object) (connection.Connection, error) {
|
|
|
|
|
if obj == nil {
|
|
|
|
|
return nil, fmt.Errorf("missing connection object")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c, ok := obj.(*provisioning.Connection)
|
|
|
|
|
if !ok {
|
|
|
|
|
return nil, fmt.Errorf("expected connection object")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Copy previous values if they exist
|
|
|
|
|
if old != nil {
|
|
|
|
|
o, ok := old.(*provisioning.Connection)
|
|
|
|
|
if ok && !o.Secure.IsZero() {
|
|
|
|
|
if c.Secure.PrivateKey.IsZero() {
|
|
|
|
|
c.Secure.PrivateKey = o.Secure.PrivateKey
|
|
|
|
|
}
|
|
|
|
|
if c.Secure.Token.IsZero() {
|
|
|
|
|
c.Secure.Token = o.Secure.Token
|
|
|
|
|
}
|
|
|
|
|
if c.Secure.ClientSecret.IsZero() {
|
|
|
|
|
c.Secure.ClientSecret = o.Secure.ClientSecret
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return b.connectionFactory.Build(ctx, c)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getJSONResponse(ref string) *spec3.Responses {
|
|
|
|
|
return &spec3.Responses{
|
|
|
|
|
ResponsesProps: spec3.ResponsesProps{
|
|
|
|
|