pkg/controller/nginxingress/default.go (131 lines of code) (raw):
package nginxingress
import (
"context"
"errors"
"fmt"
"time"
approutingv1alpha1 "github.com/Azure/aks-app-routing-operator/api/v1alpha1"
"github.com/Azure/aks-app-routing-operator/pkg/config"
"github.com/Azure/aks-app-routing-operator/pkg/controller/controllername"
"github.com/Azure/aks-app-routing-operator/pkg/controller/metrics"
"github.com/Azure/aks-app-routing-operator/pkg/util"
"github.com/go-logr/logr"
netv1 "k8s.io/api/networking/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
)
const (
// DefaultcName is the default Ingress class name
DefaultIcName = "webapprouting.kubernetes.azure.com"
// DefaultNicName is the default Nginx Ingress Controller resource name
DefaultNicName = "default"
DefaultNicResourceName = "nginx"
reconcileInterval = time.Minute * 3
retryInterval = time.Second
)
const internalLbAnnotation = "service.beta.kubernetes.io/azure-load-balancer-internal"
func NewDefaultReconciler(mgr ctrl.Manager, conf *config.Config) error {
if conf == nil {
return errors.New("nil config")
}
if conf.DefaultController == config.Off {
return nil
}
name := controllername.New("default", "nginx", "ingress", "controller", "reconciler")
metrics.InitControllerMetrics(name)
if err := mgr.Add(&defaultNicReconciler{
name: name,
lgr: name.AddToLogger(mgr.GetLogger()),
client: mgr.GetClient(),
conf: *conf,
}); err != nil {
return fmt.Errorf("adding default nginx ingress controller: %w", err)
}
return nil
}
type defaultNicReconciler struct {
name controllername.ControllerNamer
client client.Client
lgr logr.Logger
conf config.Config
}
func (d *defaultNicReconciler) Start(ctx context.Context) error {
d.lgr.Info("starting default nginx ingress controller reconciler")
interval := time.Nanosecond
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(util.Jitter(interval, 0.3)):
}
if err := d.tick(ctx); err != nil {
d.lgr.Error(err, "reconciling default nginx ingress controller")
interval = retryInterval
continue
}
interval = reconcileInterval
}
}
func (d *defaultNicReconciler) tick(ctx context.Context) (err error) {
start := time.Now()
d.lgr.Info("starting to reconcile default nginx ingress controller")
defer func() {
d.lgr.Info("finished reconciling default nginx ingress controller", "latencySec", time.Since(start).Seconds())
metrics.HandleControllerReconcileMetrics(d.name, ctrl.Result{}, err)
}()
nic := GetDefaultNginxIngressController()
switch d.conf.DefaultController {
case config.Public:
nic.Spec.LoadBalancerAnnotations = map[string]string{
internalLbAnnotation: "false",
}
case config.Private:
nic.Spec.LoadBalancerAnnotations = map[string]string{
internalLbAnnotation: "true",
}
}
d.lgr.Info("upserting default nginx ingress controller")
if err := util.Upsert(ctx, d.client, &nic); err != nil {
d.lgr.Error(err, "upserting default nginx ingress controller")
return fmt.Errorf("upserting default nginx ingress controller: %w", err)
}
return nil
}
func GetDefaultNginxIngressController() approutingv1alpha1.NginxIngressController {
return approutingv1alpha1.NginxIngressController{
TypeMeta: metav1.TypeMeta{
APIVersion: approutingv1alpha1.GroupVersion.String(),
Kind: "NginxIngressController",
},
ObjectMeta: metav1.ObjectMeta{
Name: DefaultNicName,
},
Spec: approutingv1alpha1.NginxIngressControllerSpec{
ControllerNamePrefix: DefaultNicResourceName,
IngressClassName: DefaultIcName,
},
}
}
// GetDefaultIngressClassControllerClass returns the default ingress class controller class
func GetDefaultIngressClassControllerClass(cl client.Client) (string, error) {
defaultNicCc := "webapprouting.kubernetes.azure.com/nginx"
defaultIc := &netv1.IngressClass{
ObjectMeta: metav1.ObjectMeta{
Name: DefaultIcName,
},
}
err := cl.Get(context.Background(), types.NamespacedName{Name: DefaultIcName}, defaultIc)
if err == nil {
defaultNicCc = defaultIc.Spec.Controller
}
if err != nil && !k8serrors.IsNotFound(err) {
return "", fmt.Errorf("getting default ingress class: %w", err)
}
return defaultNicCc, nil
}
// IsDefaultNic returns true if the given NginxIngressController is the default one
func IsDefaultNic(nic *approutingv1alpha1.NginxIngressController) bool {
if nic == nil {
return false
}
return nic.Name == DefaultNicName && nic.Spec.IngressClassName == DefaultIcName
}