App Installer: Merge builder and installer admission (#109854)

This commit is contained in:
Todd Treece
2025-08-19 11:58:03 -04:00
committed by GitHub
parent e159d25fdd
commit e6df473e5a
2 changed files with 39 additions and 22 deletions
@@ -2,6 +2,7 @@ package appinstaller
import (
"context"
"errors"
"fmt"
"maps"
"time"
@@ -11,6 +12,7 @@ import (
"github.com/grafana/grafana/pkg/storage/legacysql/dualwrite"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/registry/generic"
genericapiserver "k8s.io/apiserver/pkg/server"
@@ -58,27 +60,31 @@ func AddToScheme(
return additionalGroupVersions, nil
}
// RegisterAdmissionPlugins registers admission plugins for app installers
func RegisterAdmissionPlugins(
ctx context.Context,
// RegisterAdmission combines the existing admission control from builders.
func RegisterAdmission(
existingAdmission admission.Interface,
appInstallers []appsdkapiserver.AppInstaller,
options *grafanaapiserveroptions.Options,
) error {
logger := logging.FromContext(ctx)
) (admission.Interface, error) {
controllers := []admission.Interface{}
for _, installer := range appInstallers {
plugin := installer.AdmissionPlugin()
if plugin != nil {
md := installer.ManifestData()
if md == nil {
return fmt.Errorf("manifest is not initialized for installer for GroupVersions %v", installer.GroupVersions())
}
pluginName := md.AppName + " admission"
options.RecommendedOptions.Admission.Plugins.Register(pluginName, plugin)
logger.Info("Registered admission plugin", "app", md.AppName)
factory := installer.AdmissionPlugin()
if factory == nil {
continue
}
admissionInterface, err := factory(nil)
if err != nil {
return nil, fmt.Errorf("failed to create admission plugin: %w", err)
}
controllers = append(controllers, admissionInterface)
}
return nil
if existingAdmission != nil {
controllers = append(controllers, existingAdmission)
}
return admission.NewChainHandler(controllers...), nil
}
type AuthorizerRegistrar interface {
@@ -179,7 +185,7 @@ func createPostStartHook(
logger := logging.FromContext(hookContext.Context)
logger.Debug("Initializing app", "app", installer.ManifestData().AppName)
if err := installer.InitializeApp(*hookContext.LoopbackClientConfig); err != nil {
if err := installer.InitializeApp(*hookContext.LoopbackClientConfig); err != nil && !errors.Is(err, appsdkapiserver.ErrAppAlreadyInitialized) {
logger.Error("Failed to initialize app", "app", installer.ManifestData().AppName, "error", err)
return fmt.Errorf("failed to initialize app %s: %w", installer.ManifestData().AppName, err)
}
+16 -5
View File
@@ -2,6 +2,7 @@ package apiserver
import (
"context"
"errors"
"fmt"
"net/http"
"path"
@@ -291,11 +292,6 @@ func (s *service) start(ctx context.Context) error {
o := grafanaapiserveroptions.NewOptions(s.codecs.LegacyCodec(groupVersions...))
// Register admission plugins from app installers after options are created
if err := appinstaller.RegisterAdmissionPlugins(ctx, s.appInstallers, o); err != nil {
return err
}
// Register authorizers from app installers
appinstaller.RegisterAuthorizers(ctx, s.appInstallers, s.authorizer)
@@ -367,6 +363,14 @@ func (s *service) start(ctx context.Context) error {
return err
}
serverConfig.AdmissionControl, err = appinstaller.RegisterAdmission(
serverConfig.AdmissionControl,
s.appInstallers,
)
if err != nil {
return err
}
notFoundHandler := notfoundhandler.New(s.codecs, genericapifilters.NoMuxAndDiscoveryIncompleteKey)
if err := appinstaller.RegisterPostStartHooks(s.appInstallers, serverConfig); err != nil {
@@ -469,6 +473,13 @@ func (s *service) start(ctx context.Context) error {
// used by local clients to make requests to the server
s.restConfig = runningServer.LoopbackClientConfig
for _, installer := range s.appInstallers {
err := installer.InitializeApp(*s.restConfig)
if err != nil && !errors.Is(err, appsdkapiserver.ErrAppAlreadyInitialized) {
return err
}
}
return nil
}