Provisioning: add webhook support in API Server and Operator (#110673)
* Provisioning: add webhook support in API Server * updating Extra interface * adding extra with workers interface * reverting extraWithWorkers in RegisterAPIService * adding extra job worker provider * adding new extra job provider * Wire things differently * Remove unused GetJobs * Pass url variable as string * Support webhooks in controller * Fix condition * Change the naming --------- Co-authored-by: Roberto Jimenez Sanchez <roberto.jimenez@grafana.com>
This commit is contained in:
co-authored by
Roberto Jimenez Sanchez
parent
32e997d282
commit
76976ef648
@@ -106,3 +106,19 @@ func (r *screenshotRenderer) RenderScreenshot(ctx context.Context, repo provisio
|
||||
return fmt.Sprintf("apis/%s/namespaces/%s/repositories/%s/render/%s",
|
||||
provisioning.APIVERSION, repo.Namespace, repo.Name, rsp.Uid), nil
|
||||
}
|
||||
|
||||
type NoOpRenderer struct{}
|
||||
|
||||
func NewNoOpRenderer() ScreenshotRenderer {
|
||||
return &NoOpRenderer{}
|
||||
}
|
||||
|
||||
func (r *NoOpRenderer) IsAvailable(_ context.Context) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *NoOpRenderer) RenderScreenshot(
|
||||
_ context.Context, _ provisioning.ResourceRepositoryInfo, _ string, _ url.Values,
|
||||
) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -12,8 +12,33 @@ import (
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/repository"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/provisioning/resources"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/rendering"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
||||
)
|
||||
|
||||
func ProvidePullRequestWorker(
|
||||
cfg *setting.Cfg,
|
||||
renderer rendering.Service,
|
||||
blobstore resource.ResourceClient,
|
||||
configProvider apiserver.RestConfigProvider,
|
||||
) *PullRequestWorker {
|
||||
urlProvider := func(_ string) string {
|
||||
return cfg.AppURL
|
||||
}
|
||||
|
||||
// FIXME: we should create providers for client and parsers, so that we don't have
|
||||
// multiple connections for webhooks
|
||||
clients := resources.NewClientFactory(configProvider)
|
||||
parsers := resources.NewParserFactory(clients)
|
||||
screenshotRenderer := NewScreenshotRenderer(renderer, blobstore)
|
||||
evaluator := NewEvaluator(screenshotRenderer, parsers, urlProvider)
|
||||
commenter := NewCommenter()
|
||||
|
||||
return NewPullRequestWorker(evaluator, commenter)
|
||||
}
|
||||
|
||||
//go:generate mockery --name=PullRequestRepo --structname=MockPullRequestRepo --inpackage --filename=mock_pullrequest_repo.go --with-expecter
|
||||
type PullRequestRepo interface {
|
||||
Config() *provisioning.Repository
|
||||
|
||||
@@ -28,6 +28,7 @@ type WebhookExtraBuilder struct {
|
||||
urlProvider func(namespace string) string
|
||||
}
|
||||
|
||||
// FIXME: separate the URL provider from connector to simplify operators
|
||||
func (b *WebhookExtraBuilder) WebhookURL(ctx context.Context, r *provisioning.Repository) string {
|
||||
if !b.isPublic {
|
||||
return ""
|
||||
@@ -57,7 +58,7 @@ func isPublicURL(url string) bool {
|
||||
!strings.HasPrefix(url, "https://172.16.")
|
||||
}
|
||||
|
||||
func ProvideWebhooks(
|
||||
func ProvideWebhooksWithImages(
|
||||
cfg *setting.Cfg,
|
||||
renderer rendering.Service,
|
||||
blobstore resource.ResourceClient,
|
||||
@@ -87,7 +88,7 @@ func ProvideWebhooks(
|
||||
commenter := pullrequest.NewCommenter()
|
||||
pullRequestWorker := pullrequest.NewPullRequestWorker(evaluator, commenter)
|
||||
|
||||
return NewWebhookExtra(
|
||||
return NewWebhookExtraWithImages(
|
||||
render,
|
||||
webhook,
|
||||
urlProvider,
|
||||
@@ -97,21 +98,40 @@ func ProvideWebhooks(
|
||||
}
|
||||
}
|
||||
|
||||
// WebhookExtra implements the Extra interface for webhooks
|
||||
func ProvideWebhooks(provisioningURL string) *WebhookExtraBuilder {
|
||||
urlProvider := func(_ string) string {
|
||||
return provisioningURL
|
||||
}
|
||||
|
||||
isPublic := isPublicURL(urlProvider(""))
|
||||
|
||||
return &WebhookExtraBuilder{
|
||||
isPublic: isPublic,
|
||||
urlProvider: urlProvider,
|
||||
ExtraBuilder: func(b *provisioningapis.APIBuilder) provisioningapis.Extra {
|
||||
screenshotRenderer := pullrequest.NewNoOpRenderer()
|
||||
webhook := NewWebhookConnector(isPublic, b, screenshotRenderer)
|
||||
|
||||
return NewWebhookExtra(webhook)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// WebhookExtraWithImages implements the Extra interface for webhooks
|
||||
// to wrap around
|
||||
type WebhookExtra struct {
|
||||
type WebhookExtraWithImages struct {
|
||||
render *renderConnector
|
||||
webhook *webhookConnector
|
||||
workers []jobs.Worker
|
||||
}
|
||||
|
||||
func NewWebhookExtra(
|
||||
func NewWebhookExtraWithImages(
|
||||
render *renderConnector,
|
||||
webhook *webhookConnector,
|
||||
urlProvider func(namespace string) string,
|
||||
workers []jobs.Worker,
|
||||
) *WebhookExtra {
|
||||
return &WebhookExtra{
|
||||
) *WebhookExtraWithImages {
|
||||
return &WebhookExtraWithImages{
|
||||
render: render,
|
||||
webhook: webhook,
|
||||
workers: workers,
|
||||
@@ -119,7 +139,7 @@ func NewWebhookExtra(
|
||||
}
|
||||
|
||||
// Authorize delegates authorization to the webhook connector
|
||||
func (e *WebhookExtra) Authorize(ctx context.Context, a authorizer.Attributes) (decision authorizer.Decision, reason string, err error) {
|
||||
func (e *WebhookExtraWithImages) Authorize(ctx context.Context, a authorizer.Attributes) (decision authorizer.Decision, reason string, err error) {
|
||||
webhookDecision, webhookReason, webhookErr := e.webhook.Authorize(ctx, a)
|
||||
if webhookDecision != authorizer.DecisionNoOpinion {
|
||||
return webhookDecision, webhookReason, webhookErr
|
||||
@@ -129,7 +149,7 @@ func (e *WebhookExtra) Authorize(ctx context.Context, a authorizer.Attributes) (
|
||||
}
|
||||
|
||||
// UpdateStorage updates the storage with both render and webhook connectors
|
||||
func (e *WebhookExtra) UpdateStorage(storage map[string]rest.Storage) error {
|
||||
func (e *WebhookExtraWithImages) UpdateStorage(storage map[string]rest.Storage) error {
|
||||
if err := e.webhook.UpdateStorage(storage); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -138,7 +158,7 @@ func (e *WebhookExtra) UpdateStorage(storage map[string]rest.Storage) error {
|
||||
}
|
||||
|
||||
// PostProcessOpenAPI processes OpenAPI specs for both connectors
|
||||
func (e *WebhookExtra) PostProcessOpenAPI(oas *spec3.OpenAPI) error {
|
||||
func (e *WebhookExtraWithImages) PostProcessOpenAPI(oas *spec3.OpenAPI) error {
|
||||
if err := e.webhook.PostProcessOpenAPI(oas); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -146,7 +166,25 @@ func (e *WebhookExtra) PostProcessOpenAPI(oas *spec3.OpenAPI) error {
|
||||
return e.render.PostProcessOpenAPI(oas)
|
||||
}
|
||||
|
||||
// GetJobWorkers returns job workers from the webhook connector
|
||||
func (e *WebhookExtra) GetJobWorkers() []jobs.Worker {
|
||||
return e.workers
|
||||
type WebhookExtra struct {
|
||||
webhook *webhookConnector
|
||||
}
|
||||
|
||||
func NewWebhookExtra(webhook *webhookConnector) *WebhookExtra {
|
||||
return &WebhookExtra{webhook: webhook}
|
||||
}
|
||||
|
||||
// Authorize delegates authorization to the webhook connector
|
||||
func (e *WebhookExtra) Authorize(ctx context.Context, a authorizer.Attributes) (decision authorizer.Decision, reason string, err error) {
|
||||
return e.webhook.Authorize(ctx, a)
|
||||
}
|
||||
|
||||
// UpdateStorage updates the storage with webhook connector
|
||||
func (e *WebhookExtra) UpdateStorage(storage map[string]rest.Storage) error {
|
||||
return e.webhook.UpdateStorage(storage)
|
||||
}
|
||||
|
||||
// PostProcessOpenAPI processes OpenAPI specs for webhook connectors
|
||||
func (e *WebhookExtra) PostProcessOpenAPI(oas *spec3.OpenAPI) error {
|
||||
return e.webhook.PostProcessOpenAPI(oas)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user