Files
Jan Novak a78e4421ef feat: initial implementation of gateway-cert-operator
Kubernetes operator that automates HTTPS listener configuration on
Gateway API Gateway resources whenever a cert-manager Certificate is
created or updated.

Core behaviour:
- Watches cert-manager Certificate resources for the annotation
  gateway-cert-operator.io/gateway-name to identify the target Gateway
- Builds HTTPS listeners (prefixed "auto-") from each Certificate's
  DNS SANs and merges them into the target Gateway's listener list
- Preserves any manually-managed listeners; removes stale auto-listeners
  when Certificates are deleted or their annotations are removed
- Supports optional annotations to override the target namespace and
  listener port (default 443)

Components:
- main.go                            – manager setup, scheme registration,
                                       health/readiness probes
- internal/controller/               – Certificate reconciler with field
                                       indexing and dual-watch pattern
- internal/gateway/patch.go          – listener construction, merge, and
                                       equality helpers
- deploy/manifests.yaml              – Namespace, RBAC, and Deployment
- docs/README.md                     – usage guide and architecture notes
- Dockerfile                         – distroless multi-stage build

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 10:54:33 +01:00

73 lines
1.9 KiB
Go

package main
import (
"flag"
"os"
gozap "go.uber.org/zap"
cmv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
"github.com/example/gateway-cert-operator/internal/controller"
)
var scheme = runtime.NewScheme()
func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(cmv1.AddToScheme(scheme))
utilruntime.Must(gwapiv1.Install(scheme))
}
func main() {
var metricsAddr string
var probeAddr string
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metrics endpoint binds to.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
flag.Parse()
ctrl.SetLogger(zap.New(
zap.UseDevMode(true),
func(o *zap.Options) {
o.ZapOpts = append(o.ZapOpts, gozap.AddCaller())
},
))
log := ctrl.Log.WithName("setup")
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
HealthProbeBindAddress: probeAddr,
})
if err != nil {
log.Error(err, "unable to create manager")
os.Exit(1)
}
if err := controller.SetupCertificateReconciler(mgr); err != nil {
log.Error(err, "unable to setup certificate controller")
os.Exit(1)
}
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
log.Error(err, "unable to set up health check")
os.Exit(1)
}
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
log.Error(err, "unable to set up ready check")
os.Exit(1)
}
log.Info("starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
log.Error(err, "problem running manager")
os.Exit(1)
}
}