diff --git a/README.md b/README.md index 19e3a91..be80587 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,29 @@ export KUBECONFIG=.gcp/admin.kubeconfig kubectl api-resources ``` +## Batteries + +Example server contains a simple implementation of batteries that can be used to extend the gcp API. + +Batteries: +- `leases` - a Kubernetes lease resources from `coordination.k8s.io` +- `authentication` - Kubernetes native authentication using `authentication.k8s.io` +- `authorization` - Kubernetes native authorization using `authorization.k8s.io` +- `admission` - Kubernetes native admission using `admissionregistration.k8s.io` +- `flowcontrol` - Kubernetes native flow control using `flowcontrol.apiserver.k8s.io` + + +When starting server without any flags, in-memory storage will be used and batteries will be disabled by default. + +Important: In the long run, we plan to move existing apis into batteries on its own, and make default server to be a simple server without any resources. + +To start the server with batteries enabled, use the following flags: + +```bash +./bin/gcp start --batteries=lease,authentication,authorization,admission,flowcontrol +``` + + ## Contributing We ❤️ our contributors! If you're interested in helping us out, please check out [contributing to Generic Control Plane](CONTRIBUTING.md). diff --git a/server/admission/plugins.go b/server/batteries/admission.go similarity index 53% rename from server/admission/plugins.go rename to server/batteries/admission.go index d95a51e..2663189 100644 --- a/server/admission/plugins.go +++ b/server/batteries/admission.go @@ -14,11 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -package admission +package batteries import ( - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle" validatingadmissionpolicy "k8s.io/apiserver/pkg/admission/plugin/policy/validating" "k8s.io/apiserver/pkg/admission/plugin/resourcequota" @@ -29,7 +27,6 @@ import ( "k8s.io/kubernetes/plugin/pkg/admission/certificates/ctbattest" certsigning "k8s.io/kubernetes/plugin/pkg/admission/certificates/signing" certsubjectrestriction "k8s.io/kubernetes/plugin/pkg/admission/certificates/subjectrestriction" - "k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds" "k8s.io/kubernetes/plugin/pkg/admission/deny" "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit" "k8s.io/kubernetes/plugin/pkg/admission/gc" @@ -41,11 +38,10 @@ import ( // AllOrderedPlugins is the list of all the plugins in order. var AllOrderedPlugins = []string{ - admit.PluginName, // AlwaysAdmit - autoprovision.PluginName, // NamespaceAutoProvision - lifecycle.PluginName, // NamespaceLifecycle - exists.PluginName, // NamespaceExists - // limitranger.PluginName, // LimitRanger + admit.PluginName, // AlwaysAdmit + autoprovision.PluginName, // NamespaceAutoProvision + lifecycle.PluginName, // NamespaceLifecycle + exists.PluginName, // NamespaceExists serviceaccount.PluginName, // ServiceAccount eventratelimit.PluginName, // EventRateLimit gc.PluginName, // OwnerReferencesPermissionEnforcement @@ -62,45 +58,3 @@ var AllOrderedPlugins = []string{ resourcequota.PluginName, // ResourceQuota deny.PluginName, // AlwaysDeny } - -// RegisterAllAdmissionPlugins registers all admission plugins. -// The order of registration is irrelevant, see AllOrderedPlugins for execution order. -func RegisterAllAdmissionPlugins(plugins *admission.Plugins) { - admit.Register(plugins) // DEPRECATED as no real meaning - autoprovision.Register(plugins) - lifecycle.Register(plugins) - exists.Register(plugins) - // limitranger.Register(plugins) - serviceaccount.Register(plugins) - eventratelimit.Register(plugins) - gc.Register(plugins) - certapproval.Register(plugins) - certsigning.Register(plugins) - ctbattest.Register(plugins) - certsubjectrestriction.Register(plugins) - mutatingwebhook.Register(plugins) - validatingadmissionpolicy.Register(plugins) - validatingwebhook.Register(plugins) - resourcequota.Register(plugins) - deny.Register(plugins) -} - -// DefaultOffAdmissionPlugins get admission plugins off by default for kube-apiserver. -func DefaultOffAdmissionPlugins() sets.Set[string] { - defaultOnPlugins := sets.New( - lifecycle.PluginName, // NamespaceLifecycle - // limitranger.PluginName, // LimitRanger - serviceaccount.PluginName, // ServiceAccount - defaulttolerationseconds.PluginName, // DefaultTolerationSeconds - mutatingwebhook.PluginName, // MutatingAdmissionWebhook - validatingwebhook.PluginName, // ValidatingAdmissionWebhook - resourcequota.PluginName, // ResourceQuota - certapproval.PluginName, // CertificateApproval - certsigning.PluginName, // CertificateSigning - ctbattest.PluginName, // ClusterTrustBundleAttest - certsubjectrestriction.PluginName, // CertificateSubjectRestriction - validatingadmissionpolicy.PluginName, // ValidatingAdmissionPolicy, only active when feature gate ValidatingAdmissionPolicy is enabled - ) - - return sets.New[string](AllOrderedPlugins...).Difference(defaultOnPlugins) -} diff --git a/server/batteries/battery.go b/server/batteries/battery.go new file mode 100644 index 0000000..1428251 --- /dev/null +++ b/server/batteries/battery.go @@ -0,0 +1,168 @@ +package batteries + +import ( + "golang.org/x/exp/slices" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apiserver/pkg/admission" + "k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle" + validatingadmissionpolicy "k8s.io/apiserver/pkg/admission/plugin/policy/validating" + "k8s.io/apiserver/pkg/admission/plugin/resourcequota" + mutatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating" + validatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/validating" + controlplaneapiserver "k8s.io/kubernetes/pkg/controlplane/apiserver" + "k8s.io/kubernetes/plugin/pkg/admission/admit" + certapproval "k8s.io/kubernetes/plugin/pkg/admission/certificates/approval" + "k8s.io/kubernetes/plugin/pkg/admission/certificates/ctbattest" + + certsigning "k8s.io/kubernetes/plugin/pkg/admission/certificates/signing" + certsubjectrestriction "k8s.io/kubernetes/plugin/pkg/admission/certificates/subjectrestriction" + "k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds" + "k8s.io/kubernetes/plugin/pkg/admission/deny" + "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit" + "k8s.io/kubernetes/plugin/pkg/admission/gc" + "k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision" + "k8s.io/kubernetes/plugin/pkg/admission/namespace/exists" + "k8s.io/kubernetes/plugin/pkg/admission/serviceaccount" + // Admission policies +) + +type Batteries struct { + list BatteriesList + + BatteriesArgs []string +} + +type Battery string + +type BatteriesList map[Battery]BatterySpec + +type BatterySpec struct { + // Enabled indicates whether the battery is enabled. + Enabled bool + + // GroupNames is the list of group names that the battery is responsible for. + // If disabled, the battery will not be registered for these groups. + GroupNames []string +} + +const ( + // BatteryLeases is the name of the lease battery. + BatteryLeases Battery = "leases" + // BatteryAuthentication is the name of the authentication battery. + BatteryAuthentication Battery = "authentication" + // BatteryAuthorization is the name of the authorization battery. + BatteryAuthorization Battery = "authorization" + // BatteryAdmission is the name of the admission battery. + BatteryAdmission Battery = "admission" + // BatteryFlowControl is the name of the flow control battery. + BatteryFlowControl Battery = "flowcontrol" + // BatteryCRDs is the name of the CRD battery. + BatteryCRDs Battery = "crds" +) + +var ( + // The generic features. + defaultBatteries = map[Battery]BatterySpec{ + BatteryLeases: {Enabled: false, GroupNames: []string{"coordination.k8s.io"}}, + BatteryAuthentication: {Enabled: false, GroupNames: []string{"authentication.k8s.io", "rbac.authentication.k8s.io"}}, + BatteryAuthorization: {Enabled: false, GroupNames: []string{"authorization.k8s.io", "rbac.authorization.k8s.io"}}, + BatteryAdmission: {Enabled: false, GroupNames: []string{"admissionregistration.k8s.io"}}, + BatteryFlowControl: {Enabled: false, GroupNames: []string{"flowcontrol.apiserver.k8s.io"}}, + BatteryCRDs: {Enabled: false, GroupNames: []string{"apiextensions.k8s.io"}}, + } +) + +func (b Battery) String() string { + return string(b) +} + +func New() Batteries { + b := Batteries{ + list: make(BatteriesList, len(defaultBatteries)), + } + for name, spec := range defaultBatteries { + b.list[name] = spec + } + return b +} + +func (b Batteries) Enable(name Battery) { + _b := b.list[name] + _b.Enabled = true + b.list[name] = _b +} + +func (b Batteries) Disable(name Battery) { + _b := b.list[name] + _b.Enabled = false + b.list[name] = _b +} + +func (b Batteries) IsEnabled(name Battery) bool { + spec, ok := b.list[name] + return ok && spec.Enabled +} + +// RegisterAllAdmissionPlugins registers all admission plugins based on the batteries configuration. +func (b Batteries) RegisterAllAdmissionPlugins(plugins *admission.Plugins) { + admit.Register(plugins) // DEPRECATED as no real meaning + autoprovision.Register(plugins) + lifecycle.Register(plugins) + exists.Register(plugins) + serviceaccount.Register(plugins) + eventratelimit.Register(plugins) + gc.Register(plugins) + certapproval.Register(plugins) + certsigning.Register(plugins) + ctbattest.Register(plugins) + certsubjectrestriction.Register(plugins) + mutatingwebhook.Register(plugins) + validatingadmissionpolicy.Register(plugins) + validatingwebhook.Register(plugins) + resourcequota.Register(plugins) + deny.Register(plugins) +} + +func (b Batteries) DefaultOffAdmissionPlugins() sets.Set[string] { + defaultOnPlugins := sets.New( + lifecycle.PluginName, // NamespaceLifecycle + // limitranger.PluginName, // LimitRanger + serviceaccount.PluginName, // ServiceAccount + resourcequota.PluginName, // ResourceQuota + certapproval.PluginName, // CertificateApproval + certsigning.PluginName, // CertificateSigning + ctbattest.PluginName, // ClusterTrustBundleAttest + certsubjectrestriction.PluginName, // CertificateSubjectRestriction + defaulttolerationseconds.PluginName, // DefaultTolerationSeconds + ) + + if b.IsEnabled(BatteryAdmission) { + defaultOnPlugins.Insert( + mutatingwebhook.PluginName, // MutatingAdmissionWebhook + validatingwebhook.PluginName, // ValidatingAdmissionWebhook + validatingadmissionpolicy.PluginName, // ValidatingAdmissionPolicy, only active when feature gate ValidatingAdmissionPolicy is enabled + ) + } + + return sets.New[string](AllOrderedPlugins...).Difference(defaultOnPlugins) +} + +func (b Batteries) containsAndDisabled(name string) bool { + for _, spec := range b.list { + if slices.Contains(spec.GroupNames, name) && !spec.Enabled { + return true + } + } + return false +} + +func (b Batteries) FilterStorageProviders(input []controlplaneapiserver.RESTStorageProvider) []controlplaneapiserver.RESTStorageProvider { + var result []controlplaneapiserver.RESTStorageProvider + for _, rest := range input { + if b.containsAndDisabled(rest.GroupName()) { + continue + } + result = append(result, rest) + } + return result +} diff --git a/server/batteries/options.go b/server/batteries/options.go new file mode 100644 index 0000000..b2cd615 --- /dev/null +++ b/server/batteries/options.go @@ -0,0 +1,62 @@ +/* +Copyright 2024 The KCP Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package batteries + +import ( + "fmt" + + "github.com/spf13/pflag" + + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + genericfeatures "k8s.io/apiserver/pkg/features" + utilfeature "k8s.io/apiserver/pkg/util/feature" +) + +// AddFlags adds the flags for the admin authentication to the given FlagSet. +func (s *Batteries) AddFlags(fs *pflag.FlagSet) { + if s == nil { + return + } + + fs.StringSliceVar(&s.BatteriesArgs, "batteries", []string{}, "The batteries to enable in the generic control-plane server.") +} + +func (b Batteries) Complete() { + // Ensure all some related configuration are configured + + for _, name := range b.BatteriesArgs { + if _, ok := b.list[Battery(name)]; ok { + b.Enable(Battery(name)) + } + } + + // If lease is disabled, we disable APIServerIdentity + if !b.IsEnabled(BatteryLeases) { + utilruntime.Must(utilfeature.DefaultMutableFeatureGate.Set(fmt.Sprintf("%s=false", genericfeatures.APIServerIdentity))) + } +} + +func (b Batteries) Validate() []error { + var errs []error + for _, name := range b.BatteriesArgs { + fmt.Println(name) + if _, ok := b.list[Battery(name)]; !ok { + errs = append(errs, fmt.Errorf("invalid battery %q", name)) + } + } + return errs +} diff --git a/server/cmd/options/config.go b/server/cmd/options/config.go index 35a6b00..09869c5 100644 --- a/server/cmd/options/config.go +++ b/server/cmd/options/config.go @@ -28,6 +28,8 @@ import ( "k8s.io/kubernetes/pkg/controlplane" controlplaneapiserver "k8s.io/kubernetes/pkg/controlplane/apiserver" generatedopenapi "k8s.io/kubernetes/pkg/generated/openapi" + + "github.com/kcp-dev/generic-controlplane/server/batteries" ) // Config holds the configuration for the generic controlplane server. @@ -46,6 +48,8 @@ type Config struct { type ExtraConfig struct { // authentication GcpAdminToken, UserToken string + // Batteries holds the batteries configuration for the generic controlplane server. + Batteries batteries.Batteries } type completedConfig struct { @@ -68,6 +72,8 @@ type CompletedConfig struct { // Complete fills in any fields not set that are required to have valid data. func (c *Config) Complete() (CompletedConfig, error) { + c.Batteries.Complete() + return CompletedConfig{&completedConfig{ Options: c.Options, @@ -85,6 +91,9 @@ func (c *Config) Complete() (CompletedConfig, error) { func NewConfig(opts CompletedOptions) (*Config, error) { c := &Config{ Options: opts, + ExtraConfig: ExtraConfig{ + Batteries: opts.Extra.Batteries, + }, } if opts.EmbeddedEtcd.Enabled { diff --git a/server/cmd/options/options.go b/server/cmd/options/options.go index 7d46a7b..b19320d 100644 --- a/server/cmd/options/options.go +++ b/server/cmd/options/options.go @@ -37,7 +37,7 @@ import ( kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options" "k8s.io/kubernetes/pkg/serviceaccount" - gcpadmission "github.com/kcp-dev/generic-controlplane/server/admission" + "github.com/kcp-dev/generic-controlplane/server/batteries" "github.com/kcp-dev/generic-controlplane/server/tokengetter" ) @@ -53,7 +53,8 @@ type Options struct { // ExtraOptions holds the extra configuration for the generic controlplane server. type ExtraOptions struct { - RootDir string + RootDir string + Batteries batteries.Batteries } type completedOptions struct { @@ -77,7 +78,8 @@ func NewOptions(rootDir string) *Options { EmbeddedEtcd: *etcdoptions.NewOptions(rootDir), AdminAuthentication: *NewAdminAuthentication(rootDir), Extra: ExtraOptions{ - RootDir: rootDir, + RootDir: rootDir, + Batteries: batteries.New(), }, } @@ -128,8 +130,7 @@ func (o *Options) AddFlags(fss *cliflag.NamedFlagSets) { o.EmbeddedEtcd.AddFlags(fss.FlagSet("Embedded etcd")) o.AdminAuthentication.AddFlags(fss.FlagSet("GCP Standalone Authentication")) - // fs := fss.FlagSet("GCP") - // Placeholders for future flags. + o.Extra.Batteries.AddFlags(fss.FlagSet("Batteries")) } // Complete fills in any fields not set that are required to have valid data. @@ -139,6 +140,8 @@ func (o *Options) Complete() (*CompletedOptions, error) { o.EmbeddedEtcd.Enabled = true } + o.Extra.Batteries.Complete() + var serviceAccountFile string if len(o.GenericControlPlane.Authentication.ServiceAccounts.KeyFiles) == 0 { // use sa.key and auto-generate if not existing @@ -170,9 +173,9 @@ func (o *Options) Complete() (*CompletedOptions, error) { } // override set of admission plugins - gcpadmission.RegisterAllAdmissionPlugins(o.GenericControlPlane.Admission.GenericAdmission.Plugins) - o.GenericControlPlane.Admission.GenericAdmission.DisablePlugins = sets.List[string](gcpadmission.DefaultOffAdmissionPlugins()) - o.GenericControlPlane.Admission.GenericAdmission.RecommendedPluginOrder = gcpadmission.AllOrderedPlugins + o.Extra.Batteries.RegisterAllAdmissionPlugins(o.GenericControlPlane.Admission.GenericAdmission.Plugins) + o.GenericControlPlane.Admission.GenericAdmission.DisablePlugins = sets.List[string](o.Extra.Batteries.DefaultOffAdmissionPlugins()) + o.GenericControlPlane.Admission.GenericAdmission.RecommendedPluginOrder = batteries.AllOrderedPlugins var err error if !filepath.IsAbs(o.EmbeddedEtcd.Directory) { @@ -224,6 +227,7 @@ func (o *CompletedOptions) Validate() []error { errs = append(errs, o.GenericControlPlane.Validate()...) errs = append(errs, o.EmbeddedEtcd.Validate()...) errs = append(errs, o.AdminAuthentication.Validate()...) + errs = append(errs, o.Extra.Batteries.Validate()...) return errs } diff --git a/server/cmd/server.go b/server/cmd/server.go index 0db7005..7c72f68 100644 --- a/server/cmd/server.go +++ b/server/cmd/server.go @@ -26,7 +26,6 @@ import ( "github.com/kcp-dev/kcp/pkg/embeddedetcd" "github.com/spf13/cobra" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" kerrors "k8s.io/apimachinery/pkg/util/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" _ "k8s.io/apiserver/pkg/admission" // for admission plugins @@ -39,6 +38,8 @@ import ( cliflag "k8s.io/component-base/cli/flag" "k8s.io/component-base/cli/globalflag" "k8s.io/component-base/logs" + + apiextensionapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver" logsapi "k8s.io/component-base/logs/api/v1" _ "k8s.io/component-base/metrics/prometheus/workqueue" // for workqueue metrics "k8s.io/component-base/term" @@ -49,13 +50,13 @@ import ( controlplaneapiserver "k8s.io/kubernetes/pkg/controlplane/apiserver" _ "k8s.io/kubernetes/pkg/features" // add the kubernetes feature gates + "github.com/kcp-dev/generic-controlplane/server/batteries" options "github.com/kcp-dev/generic-controlplane/server/cmd/options" "github.com/kcp-dev/generic-controlplane/server/readiness" - // add the kubernetes feature gates ) // Order for settings: -// Options -> CompletedOptions -> Config -> CompletedOptions -> Server -> Prepared -> Run +// Options -> CompletedOptions -> Config -> CompletedConfig -> Server -> Prepared -> Run func init() { utilruntime.Must(logsapi.AddFeatureGates(utilfeature.DefaultMutableFeatureGate)) @@ -233,19 +234,34 @@ func Run(ctx context.Context, opts options.CompletedOptions) error { // createServerChain creates the apiservers connected via delegation. func createServerChain(config options.CompletedConfig) (*aggregatorapiserver.APIAggregator, error) { - // 1. CRDs + // 1. Basic not found handler notFoundHandler := notfoundhandler.New(config.ControlPlane.Generic.Serializer, genericapifilters.NoMuxAndDiscoveryIncompleteKey) - apiExtensionsServer, err := config.APIExtensions.New(genericapiserver.NewEmptyDelegateWithCustomHandler(notFoundHandler)) - if err != nil { - return nil, fmt.Errorf("failed to create apiextensions-apiserver: %w", err) - } - crdAPIEnabled := config.APIExtensions.GenericConfig.MergedResourceConfig.ResourceEnabled(apiextensionsv1.SchemeGroupVersion.WithResource("customresourcedefinitions")) - // 2. Natively implemented resources - nativeAPIs, err := config.ControlPlane.New("generic-controlplane", apiExtensionsServer.GenericAPIServer) - if err != nil { - return nil, fmt.Errorf("failed to create generic controlplane apiserver: %w", err) + var aggregatorServer *aggregatorapiserver.APIAggregator + var apiExtensionsServer *apiextensionapiserver.CustomResourceDefinitions + var nativeAPIs *controlplaneapiserver.Server + var err error + + if config.Batteries.IsEnabled(batteries.BatteryCRDs) { + // Base of CRDs are extension server + apiExtensionsServer, err = config.APIExtensions.New(genericapiserver.NewEmptyDelegateWithCustomHandler(notFoundHandler)) + if err != nil { + return nil, fmt.Errorf("failed to create apiextensions-apiserver: %w", err) + } + + nativeAPIs, err = config.ControlPlane.New("generic-controlplane", apiExtensionsServer.GenericAPIServer) + if err != nil { + return nil, fmt.Errorf("failed to create generic controlplane apiserver: %w", err) + } + } else { + // 2. Natively implemented resources + var err error + nativeAPIs, err = config.ControlPlane.New("generic-controlplane", genericapiserver.NewEmptyDelegateWithCustomHandler(notFoundHandler)) + if err != nil { + return nil, fmt.Errorf("failed to create generic controlplane apiserver: %w", err) + } } + client, err := kubernetes.NewForConfig(config.ControlPlane.Generic.LoopbackClientConfig) if err != nil { return nil, err @@ -254,12 +270,25 @@ func createServerChain(config options.CompletedConfig) (*aggregatorapiserver.API if err != nil { return nil, fmt.Errorf("failed to create storage providers: %w", err) } + + // Filter out the disabled batteries + storageProviders = config.Batteries.FilterStorageProviders(storageProviders) + if err := nativeAPIs.InstallAPIs(storageProviders...); err != nil { return nil, fmt.Errorf("failed to install APIs: %w", err) } + for _, storageProvider := range storageProviders { + klog.Infof("Serving %s", storageProvider.GroupName()) + } // 3. Aggregator for APIServices, discovery and OpenAPI - aggregatorServer, err := controlplaneapiserver.CreateAggregatorServer(config.Aggregator, nativeAPIs.GenericAPIServer, apiExtensionsServer.Informers.Apiextensions().V1().CustomResourceDefinitions(), crdAPIEnabled, controlplaneapiserver.DefaultGenericAPIServicePriorities()) + // If CRDs are enabled, we wire in, else - its a no-op. + if config.Batteries.IsEnabled(batteries.BatteryCRDs) { + aggregatorServer, err = controlplaneapiserver.CreateAggregatorServer(config.Aggregator, nativeAPIs.GenericAPIServer, apiExtensionsServer.Informers.Apiextensions().V1().CustomResourceDefinitions(), false, controlplaneapiserver.DefaultGenericAPIServicePriorities()) + } else { + klog.Info("CRDs are disabled, skipping aggregator server") + aggregatorServer, err = controlplaneapiserver.CreateAggregatorServer(config.Aggregator, nativeAPIs.GenericAPIServer, nil, false, controlplaneapiserver.DefaultGenericAPIServicePriorities()) + } if err != nil { // we don't need special handling for innerStopCh because the aggregator server doesn't create any go routines return nil, fmt.Errorf("failed to create kube-aggregator: %w", err) @@ -267,3 +296,13 @@ func createServerChain(config options.CompletedConfig) (*aggregatorapiserver.API return aggregatorServer, nil } + +type ControlPlaneBattery string + +const ( + ControlPlaneBatteryCore ControlPlaneBattery = "core" + ControlPlaneBatteryFlowControl ControlPlaneBattery = "flowcontrol" + ControlPlaneBatteryRBAC ControlPlaneBattery = "rbac" + ControlPlaneBatteryAdmission ControlPlaneBattery = "admission" + ControlPlaneBatteryLease ControlPlaneBattery = "lease" +) diff --git a/server/readiness/ready.go b/server/readiness/ready.go index d6507f4..60bdfb9 100644 --- a/server/readiness/ready.go +++ b/server/readiness/ready.go @@ -44,6 +44,7 @@ func WaitForReady(ctx context.Context, kubeConfigPath string) error { res := client.RESTClient().Get().AbsPath("/readyz").Do(ctx) if _, err := res.Raw(); err != nil { unreadyComponents := unreadyComponentsFromError(err) + //logger.Error(err, "control plane not ready", "unreadyComponents", sets.List[string](unreadyComponents), "error", err) if !lastSeenUnready.Equal(unreadyComponents) { logger.Error(err, "control plane not ready", "unreadyComponents", sets.List[string](unreadyComponents), "error", err) lastSeenUnready = unreadyComponents