blob: 848f98372044dccf438a63dc7f0366a7a1a42dac [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 manager
import (
"context"
"crypto/tls"
"os"
)
import (
"controllers/api/v1alpha1"
"controllers/internal/controller"
"controllers/internal/controller/config"
"controllers/internal/controller/status"
"github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/utils/ptr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/webhook"
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
"sigs.k8s.io/gateway-api/apis/v1beta1"
)
var (
scheme = runtime.NewScheme()
)
func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
if err := gatewayv1.Install(scheme); err != nil {
panic(err)
}
if err := v1alpha1.AddToScheme(scheme); err != nil {
panic(err)
}
if err := v1beta1.Install(scheme); err != nil {
panic(err)
}
// +kubebuilder:scaffold:scheme
}
func Run(ctx context.Context, logger logr.Logger) error {
cfg := config.ControllerConfig
setupLog := ctrl.LoggerFrom(ctx).WithName("setup")
disableHTTP2 := func(c *tls.Config) {
setupLog.Info("disabling http/2")
c.NextProtos = []string{"http/1.1"}
}
var tlsOpts []func(*tls.Config)
if !cfg.EnableHTTP2 {
tlsOpts = append(tlsOpts, disableHTTP2)
}
webhookServer := webhook.NewServer(webhook.Options{
TLSOpts: tlsOpts,
})
metricsServerOptions := metricsserver.Options{
BindAddress: cfg.MetricsAddr,
SecureServing: cfg.SecureMetrics,
TLSOpts: tlsOpts,
}
if cfg.SecureMetrics {
metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization
}
namespace := os.Getenv("POD_NAMESPACE")
if namespace == "" {
namespace = "default"
}
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Metrics: metricsServerOptions,
WebhookServer: webhookServer,
HealthProbeBindAddress: cfg.ProbeAddr,
LeaderElection: !config.ControllerConfig.LeaderElection.Disable,
LeaderElectionID: cfg.LeaderElectionID,
LeaderElectionNamespace: namespace,
LeaseDuration: ptr.To(config.ControllerConfig.LeaderElection.LeaseDuration.Duration),
RenewDeadline: ptr.To(config.ControllerConfig.LeaderElection.RenewDeadline.Duration),
RetryPeriod: ptr.To(config.ControllerConfig.LeaderElection.RetryPeriod.Duration),
// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily
// when the Manager ends. This requires the binary to immediately end when the
// Manager is stopped, otherwise, this setting is unsafe. Setting this significantly
// speeds up voluntary leader transitions as the new leader don't have to wait
// LeaseDuration time first.
//
// In the default scaffold provided, the program ends immediately after
// the manager stops, so would be fine to enable this option. However,
// if you are doing or is intended to do any operation such as perform cleanups
// after the manager stops then its usage might be unsafe.
// LeaderElectionReleaseOnCancel: true,
})
if err != nil {
setupLog.Error(err, "unable to start manager")
return err
}
updater := status.NewStatusUpdateHandler(ctrl.LoggerFrom(ctx).WithName("status").WithName("updater"), mgr.GetClient())
if err := mgr.Add(updater); err != nil {
setupLog.Error(err, "unable to add status updater")
return err
}
setupLog.Info("check ReferenceGrants is enabled")
_, err = mgr.GetRESTMapper().KindsFor(schema.GroupVersionResource{
Group: v1beta1.GroupVersion.Group,
Version: v1beta1.GroupVersion.Version,
Resource: "referencegrants",
})
if err != nil {
setupLog.Info("CRD ReferenceGrants is not installed", "err", err)
}
controller.SetEnableReferenceGrant(err == nil)
setupLog.Info("setting up controllers")
controllers, err := setupControllers(ctx, mgr, updater.Writer())
if err != nil {
setupLog.Error(err, "unable to set up controllers")
return err
}
for _, c := range controllers {
if err := c.SetupWithManager(mgr); err != nil {
return err
}
}
// +kubebuilder:scaffold:builder
setupLog.Info("setting up health checks")
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up health check")
return err
}
setupLog.Info("setting up ready checks")
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up ready check")
return err
}
setupLog.Info("starting controller manager")
return mgr.Start(ctrl.SetupSignalHandler())
}