Files
grafana/pkg/operators/provisioning/connection_operator.go
Roberto Jiménez Sánchez eb6c22af36 Provisioning: Add connection operator with health check updates (#116028)
* Add connection operator with health check updates

- Add ConnectionController to watch and reconcile Connection resources
- Add ConnectionStatusPatcher for updating connection status
- Add connection_operator.go entry point for standalone operator
- Register connection operator in pkg/operators/register.go
- Add connection controller to in-process setup in register.go
- Add unit tests for connection controller
- Add integration tests for health check updates

* Fix integration test: get latest version before update to avoid conflicts

* refactor: move repoFactory to operator-specific configs

- Remove repoFactory from shared provisioningControllerConfig
- Add repoFactory to repoControllerConfig and jobsControllerConfig
- This allows connection operator to run without repository setup

* Remove unneccesary comments
2026-01-09 09:08:49 +01:00

87 lines
2.6 KiB
Go

package provisioning
import (
"context"
"fmt"
"log/slog"
"os"
"os/signal"
"syscall"
"github.com/grafana/grafana-app-sdk/logging"
"github.com/prometheus/client_golang/prometheus"
"k8s.io/client-go/tools/cache"
appcontroller "github.com/grafana/grafana/apps/provisioning/pkg/controller"
informer "github.com/grafana/grafana/apps/provisioning/pkg/generated/informers/externalversions"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/controller"
"github.com/grafana/grafana/pkg/server"
"github.com/grafana/grafana/pkg/setting"
)
// RunConnectionController starts the connection controller operator.
func RunConnectionController(deps server.OperatorDependencies) error {
logger := logging.NewSLogLogger(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelDebug,
})).With("logger", "provisioning-connection-controller")
logger.Info("Starting provisioning connection controller")
controllerCfg, err := getConnectionControllerConfig(deps.Config, deps.Registerer)
if err != nil {
return fmt.Errorf("failed to setup operator: %w", err)
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigChan
fmt.Println("Received shutdown signal, stopping controllers")
cancel()
}()
informerFactory := informer.NewSharedInformerFactoryWithOptions(
controllerCfg.provisioningClient,
controllerCfg.resyncInterval,
)
statusPatcher := appcontroller.NewConnectionStatusPatcher(controllerCfg.provisioningClient.ProvisioningV0alpha1())
connInformer := informerFactory.Provisioning().V0alpha1().Connections()
connController, err := controller.NewConnectionController(
controllerCfg.provisioningClient.ProvisioningV0alpha1(),
connInformer,
statusPatcher,
)
if err != nil {
return fmt.Errorf("failed to create connection controller: %w", err)
}
informerFactory.Start(ctx.Done())
if !cache.WaitForCacheSync(ctx.Done(), connInformer.Informer().HasSynced) {
return fmt.Errorf("failed to sync informer cache")
}
connController.Run(ctx, controllerCfg.workerCount)
return nil
}
type connectionControllerConfig struct {
provisioningControllerConfig
workerCount int
}
func getConnectionControllerConfig(cfg *setting.Cfg, registry prometheus.Registerer) (*connectionControllerConfig, error) {
controllerCfg, err := setupFromConfig(cfg, registry)
if err != nil {
return nil, err
}
return &connectionControllerConfig{
provisioningControllerConfig: *controllerCfg,
workerCount: cfg.SectionWithEnvOverrides("operator").Key("worker_count").MustInt(1),
}, nil
}