Files
grafana/pkg/registry/apps/apps.go
T
Austin Pond bf65c43783 Apps: Add Example App to ./apps (#112069)
* [API Server] Add Example App for reference use.

* Remove Printlns.

* Upgrade app-sdk to v0.46.0, update apps to handle breaking changes.

* Only start the reconciler for the example app if the v1alpha1 API version is enabled.

* Some comment doc updates.

* Run make update-workspace

* Set codeowner for /apps/example

* Run make gofmt and make update-workspace

* Run prettier on apps/example/README.md

* Add COPY apps/example to Dockerfile

* Add an authorizer to the example app.

* Fix import ordering.

* Update apps/example/kinds/manifest.cue

Co-authored-by: Owen Diehl <ow.diehl@gmail.com>

* Run make update-workspace

* Re-run make gen-go for enterprise import updates

* Run make update-workspace

---------

Co-authored-by: Owen Diehl <ow.diehl@gmail.com>
2025-10-27 12:01:10 -04:00

133 lines
4.7 KiB
Go

package appregistry
import (
"context"
"slices"
"k8s.io/client-go/rest"
"github.com/grafana/grafana-app-sdk/app"
appsdkapiserver "github.com/grafana/grafana-app-sdk/k8s/apiserver"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/registry/apps/advisor"
"github.com/grafana/grafana/pkg/registry/apps/alerting/notifications"
"github.com/grafana/grafana/pkg/registry/apps/alerting/rules"
"github.com/grafana/grafana/pkg/registry/apps/correlations"
"github.com/grafana/grafana/pkg/registry/apps/example"
"github.com/grafana/grafana/pkg/registry/apps/investigations"
"github.com/grafana/grafana/pkg/registry/apps/logsdrilldown"
"github.com/grafana/grafana/pkg/registry/apps/playlist"
"github.com/grafana/grafana/pkg/registry/apps/plugins"
"github.com/grafana/grafana/pkg/registry/apps/shorturl"
"github.com/grafana/grafana/pkg/services/apiserver"
"github.com/grafana/grafana/pkg/services/apiserver/builder"
"github.com/grafana/grafana/pkg/services/apiserver/builder/runner"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/setting"
)
// ProvideAppInstallers returns a list of app installers that can be used to install apps.
// This is the pattern that should be used to provide app installers in the app registry.
func ProvideAppInstallers(
features featuremgmt.FeatureToggles,
playlistAppInstaller *playlist.PlaylistAppInstaller,
pluginsApplInstaller *plugins.PluginsAppInstaller,
shorturlAppInstaller *shorturl.ShortURLAppInstaller,
rulesAppInstaller *rules.AlertingRulesAppInstaller,
correlationsAppInstaller *correlations.AppInstaller,
alertingNotificationAppInstaller *notifications.AlertingNotificationsAppInstaller,
logsdrilldownAppInstaller *logsdrilldown.LogsDrilldownAppInstaller,
exampleAppInstaller *example.ExampleAppInstaller,
) []appsdkapiserver.AppInstaller {
installers := []appsdkapiserver.AppInstaller{
playlistAppInstaller,
pluginsApplInstaller,
exampleAppInstaller,
}
//nolint:staticcheck // not yet migrated to OpenFeature
if features.IsEnabledGlobally(featuremgmt.FlagKubernetesShortURLs) {
installers = append(installers, shorturlAppInstaller)
}
//nolint:staticcheck // not yet migrated to OpenFeature
if features.IsEnabledGlobally(featuremgmt.FlagKubernetesAlertingRules) && rulesAppInstaller != nil {
installers = append(installers, rulesAppInstaller)
}
//nolint:staticcheck // not yet migrated to OpenFeature
if features.IsEnabledGlobally(featuremgmt.FlagKubernetesCorrelations) {
installers = append(installers, correlationsAppInstaller)
}
if alertingNotificationAppInstaller != nil {
installers = append(installers, alertingNotificationAppInstaller)
}
//nolint:staticcheck // not yet migrated to OpenFeature
if features.IsEnabledGlobally(featuremgmt.FlagKubernetesLogsDrilldown) {
installers = append(installers, logsdrilldownAppInstaller)
}
return installers
}
var (
_ registry.BackgroundService = (*Service)(nil)
)
type Service struct {
runner *runner.APIGroupRunner
log log.Logger
}
// ProvideBuilderRunners adapts apps to the APIGroupBuilder interface.
// deprecated: Use ProvideAppInstallers instead.
func ProvideBuilderRunners(
registrar builder.APIRegistrar,
restConfigProvider apiserver.RestConfigProvider,
features featuremgmt.FeatureToggles,
investigationAppProvider *investigations.InvestigationsAppProvider,
advisorAppProvider *advisor.AdvisorAppProvider,
grafanaCfg *setting.Cfg,
) (*Service, error) {
cfgWrapper := func(ctx context.Context) (*rest.Config, error) {
cfg, err := restConfigProvider.GetRestConfig(ctx)
if err != nil {
return nil, err
}
cfg.APIPath = "/apis"
return cfg, nil
}
cfg := runner.RunnerConfig{
RestConfigGetter: cfgWrapper,
APIRegistrar: registrar,
}
logger := log.New("app-registry")
var apiGroupRunner *runner.APIGroupRunner
var err error
providers := []app.Provider{}
//nolint:staticcheck // not yet migrated to OpenFeature
if features.IsEnabledGlobally(featuremgmt.FlagInvestigationsBackend) {
logger.Debug("Investigations backend is enabled")
providers = append(providers, investigationAppProvider)
}
//nolint:staticcheck // not yet migrated to OpenFeature
if features.IsEnabledGlobally(featuremgmt.FlagGrafanaAdvisor) &&
!slices.Contains(grafanaCfg.DisablePlugins, "grafana-advisor-app") {
providers = append(providers, advisorAppProvider)
}
apiGroupRunner, err = runner.NewAPIGroupRunner(cfg, providers...)
if err != nil {
return nil, err
}
return &Service{runner: apiGroupRunner, log: logger}, nil
}
func (s *Service) Run(ctx context.Context) error {
s.log.Debug("initializing app registry")
if err := s.runner.Init(ctx); err != nil {
return err
}
s.log.Info("app registry initialized")
return s.runner.Run(ctx)
}