Skip to content

Commit 6f4b948

Browse files
authored
refactor: add extension config (#100)
Add extension config to `main.go` to allow extension configs to be provided directly to the controller. This allows downstream forks to easily extend the main controller with plugins and additional schemes easily. --------- Signed-off-by: JM Huibonhoa <jm.huibonhoa@solo.io>
1 parent 0296869 commit 6f4b948

7 files changed

Lines changed: 367 additions & 226 deletions

File tree

cmd/main.go

Lines changed: 6 additions & 216 deletions
Original file line numberDiff line numberDiff line change
@@ -17,229 +17,19 @@ limitations under the License.
1717
package main
1818

1919
import (
20-
"crypto/tls"
21-
"flag"
22-
"os"
23-
"path/filepath"
24-
2520
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
2621
// to ensure that exec-entrypoint and run can make use of them.
2722
_ "k8s.io/client-go/plugin/pkg/client/auth"
2823

29-
"k8s.io/apimachinery/pkg/runtime"
30-
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
31-
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
32-
ctrl "sigs.k8s.io/controller-runtime"
33-
"sigs.k8s.io/controller-runtime/pkg/certwatcher"
34-
"sigs.k8s.io/controller-runtime/pkg/healthz"
35-
"sigs.k8s.io/controller-runtime/pkg/log/zap"
36-
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
37-
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
38-
"sigs.k8s.io/controller-runtime/pkg/webhook"
39-
40-
kagentdevv1alpha1 "github.com/kagent-dev/kmcp/api/v1alpha1"
41-
"github.com/kagent-dev/kmcp/pkg/controller"
24+
"github.com/kagent-dev/kmcp/pkg/app"
4225
// +kubebuilder:scaffold:imports
4326
)
4427

45-
var (
46-
scheme = runtime.NewScheme()
47-
setupLog = ctrl.Log.WithName("setup")
48-
)
49-
50-
func init() {
51-
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
52-
53-
utilruntime.Must(kagentdevv1alpha1.AddToScheme(scheme))
54-
// +kubebuilder:scaffold:scheme
55-
}
56-
57-
// nolint:gocyclo
5828
func main() {
59-
var metricsAddr string
60-
var metricsCertPath, metricsCertName, metricsCertKey string
61-
var webhookCertPath, webhookCertName, webhookCertKey string
62-
var enableLeaderElection bool
63-
var probeAddr string
64-
var secureMetrics bool
65-
var enableHTTP2 bool
66-
var tlsOpts []func(*tls.Config)
67-
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
68-
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
69-
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
70-
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
71-
"Enable leader election for controller manager. "+
72-
"Enabling this will ensure there is only one active controller manager.")
73-
flag.BoolVar(&secureMetrics, "metrics-secure", true,
74-
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
75-
flag.StringVar(&webhookCertPath, "webhook-cert-path", "", "The directory that contains the webhook certificate.")
76-
flag.StringVar(&webhookCertName, "webhook-cert-name", "tls.crt", "The name of the webhook certificate file.")
77-
flag.StringVar(&webhookCertKey, "webhook-cert-key", "tls.key", "The name of the webhook key file.")
78-
flag.StringVar(&metricsCertPath, "metrics-cert-path", "",
79-
"The directory that contains the metrics server certificate.")
80-
flag.StringVar(&metricsCertName, "metrics-cert-name", "tls.crt", "The name of the metrics server certificate file.")
81-
flag.StringVar(&metricsCertKey, "metrics-cert-key", "tls.key", "The name of the metrics server key file.")
82-
flag.BoolVar(&enableHTTP2, "enable-http2", false,
83-
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
84-
opts := zap.Options{
85-
Development: true,
86-
}
87-
opts.BindFlags(flag.CommandLine)
88-
flag.Parse()
89-
90-
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
91-
92-
// if the enable-http2 flag is false (the default), http/2 should be disabled
93-
// due to its vulnerabilities. More specifically, disabling http/2 will
94-
// prevent from being vulnerable to the HTTP/2 Stream Cancellation and
95-
// Rapid Reset CVEs. For more information see:
96-
// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3
97-
// - https://github.com/advisories/GHSA-4374-p667-p6c8
98-
disableHTTP2 := func(c *tls.Config) {
99-
setupLog.Info("disabling http/2")
100-
c.NextProtos = []string{"http/1.1"}
101-
}
102-
103-
if !enableHTTP2 {
104-
tlsOpts = append(tlsOpts, disableHTTP2)
105-
}
106-
107-
// Create watchers for metrics and webhooks certificates
108-
var metricsCertWatcher, webhookCertWatcher *certwatcher.CertWatcher
109-
110-
// Initial webhook TLS options
111-
webhookTLSOpts := tlsOpts
112-
113-
if len(webhookCertPath) > 0 {
114-
setupLog.Info("Initializing webhook certificate watcher using provided certificates",
115-
"webhook-cert-path", webhookCertPath, "webhook-cert-name", webhookCertName, "webhook-cert-key", webhookCertKey)
116-
117-
var err error
118-
webhookCertWatcher, err = certwatcher.New(
119-
filepath.Join(webhookCertPath, webhookCertName),
120-
filepath.Join(webhookCertPath, webhookCertKey),
121-
)
122-
if err != nil {
123-
setupLog.Error(err, "Failed to initialize webhook certificate watcher")
124-
os.Exit(1)
125-
}
126-
127-
webhookTLSOpts = append(webhookTLSOpts, func(config *tls.Config) {
128-
config.GetCertificate = webhookCertWatcher.GetCertificate
129-
})
130-
}
131-
132-
webhookServer := webhook.NewServer(webhook.Options{
133-
TLSOpts: webhookTLSOpts,
134-
})
135-
136-
// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
137-
// More info:
138-
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.20.0/pkg/metrics/server
139-
// - https://book.kubebuilder.io/reference/metrics.html
140-
metricsServerOptions := metricsserver.Options{
141-
BindAddress: metricsAddr,
142-
SecureServing: secureMetrics,
143-
TLSOpts: tlsOpts,
144-
}
145-
146-
if secureMetrics {
147-
// FilterProvider is used to protect the metrics endpoint with authn/authz.
148-
// These configurations ensure that only authorized users and service accounts
149-
// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
150-
// https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.20.0/pkg/metrics/filters#WithAuthenticationAndAuthorization
151-
metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization
152-
}
153-
154-
// If the certificate is not specified, controller-runtime will automatically
155-
// generate self-signed certificates for the metrics server. While convenient for development and testing,
156-
// this setup is not recommended for production.
157-
//
158-
// TODO(user): If you enable certManager, uncomment the following lines:
159-
// - [METRICS-WITH-CERTS] at config/default/kustomization.yaml to generate and use certificates
160-
// managed by cert-manager for the metrics server.
161-
// - [PROMETHEUS-WITH-CERTS] at config/prometheus/kustomization.yaml for TLS certification.
162-
if len(metricsCertPath) > 0 {
163-
setupLog.Info("Initializing metrics certificate watcher using provided certificates",
164-
"metrics-cert-path", metricsCertPath, "metrics-cert-name", metricsCertName, "metrics-cert-key", metricsCertKey)
165-
166-
var err error
167-
metricsCertWatcher, err = certwatcher.New(
168-
filepath.Join(metricsCertPath, metricsCertName),
169-
filepath.Join(metricsCertPath, metricsCertKey),
170-
)
171-
if err != nil {
172-
setupLog.Error(err, "to initialize metrics certificate watcher", "error", err)
173-
os.Exit(1)
174-
}
175-
176-
metricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, func(config *tls.Config) {
177-
config.GetCertificate = metricsCertWatcher.GetCertificate
178-
})
179-
}
180-
181-
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
182-
Scheme: scheme,
183-
Metrics: metricsServerOptions,
184-
WebhookServer: webhookServer,
185-
HealthProbeBindAddress: probeAddr,
186-
LeaderElection: enableLeaderElection,
187-
LeaderElectionID: "90217b08.kagent.dev",
188-
// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily
189-
// when the Manager ends. This requires the binary to immediately end when the
190-
// Manager is stopped, otherwise, this setting is unsafe. Setting this significantly
191-
// speeds up voluntary leader transitions as the new leader don't have to wait
192-
// LeaseDuration time first.
193-
//
194-
// In the default scaffold provided, the program ends immediately after
195-
// the manager stops, so would be fine to enable this option. However,
196-
// if you are doing or is intended to do any operation such as perform cleanups
197-
// after the manager stops then its usage might be unsafe.
198-
// LeaderElectionReleaseOnCancel: true,
29+
app.Start(func() (*app.ExtensionConfig, error) {
30+
return &app.ExtensionConfig{
31+
PluginFactories: nil,
32+
RegisterSchemes: nil,
33+
}, nil
19934
})
200-
if err != nil {
201-
setupLog.Error(err, "unable to start manager")
202-
os.Exit(1)
203-
}
204-
205-
if err = (&controller.MCPServerReconciler{
206-
Client: mgr.GetClient(),
207-
Scheme: mgr.GetScheme(),
208-
Plugins: nil, // Plugins are for 3rd party extensions to open source.
209-
}).SetupWithManager(mgr); err != nil {
210-
setupLog.Error(err, "unable to create controller", "controller", "MCPServer")
211-
os.Exit(1)
212-
}
213-
// +kubebuilder:scaffold:builder
214-
215-
if metricsCertWatcher != nil {
216-
setupLog.Info("Adding metrics certificate watcher to manager")
217-
if err := mgr.Add(metricsCertWatcher); err != nil {
218-
setupLog.Error(err, "unable to add metrics certificate watcher to manager")
219-
os.Exit(1)
220-
}
221-
}
222-
223-
if webhookCertWatcher != nil {
224-
setupLog.Info("Adding webhook certificate watcher to manager")
225-
if err := mgr.Add(webhookCertWatcher); err != nil {
226-
setupLog.Error(err, "unable to add webhook certificate watcher to manager")
227-
os.Exit(1)
228-
}
229-
}
230-
231-
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
232-
setupLog.Error(err, "unable to set up health check")
233-
os.Exit(1)
234-
}
235-
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
236-
setupLog.Error(err, "unable to set up ready check")
237-
os.Exit(1)
238-
}
239-
240-
setupLog.Info("starting manager")
241-
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
242-
setupLog.Error(err, "problem running manager")
243-
os.Exit(1)
244-
}
24535
}

0 commit comments

Comments
 (0)