@@ -20,6 +20,7 @@ import (
2020 "net/http"
2121 "os"
2222 "strconv"
23+ "strings"
2324 "time"
2425
2526 "github.com/alecthomas/kingpin/v2"
@@ -145,8 +146,6 @@ func registerServe(app *kingpin.Application) (*kingpin.CmdClause, *serveContext)
145146 serve .Flag ("envoy-service-https-port" , "Kubernetes Service port for HTTPS requests." ).PlaceHolder ("<port>" ).IntVar (& ctx .httpsPort )
146147 serve .Flag ("envoy-service-name" , "Name of the Envoy service to inspect for Ingress status details." ).PlaceHolder ("<name>" ).StringVar (& ctx .Config .EnvoyServiceName )
147148 serve .Flag ("envoy-service-namespace" , "Envoy Service Namespace." ).PlaceHolder ("<namespace>" ).StringVar (& ctx .Config .EnvoyServiceNamespace )
148- serve .Flag ("envoy-ingress-name" , "Name of the Envoy ingress to inspect for Ingress status details." ).PlaceHolder ("<name>" ).StringVar (& ctx .Config .EnvoyIngressName )
149- serve .Flag ("envoy-ingress-namespace" , "Envoy Ingress Namespace." ).PlaceHolder ("<namespace>" ).StringVar (& ctx .Config .EnvoyIngressNamespace )
150149
151150 serve .Flag ("health-address" , "Address the health HTTP endpoint will bind to." ).PlaceHolder ("<ipaddr>" ).StringVar (& ctx .healthAddr )
152151 serve .Flag ("health-port" , "Port the health HTTP endpoint will bind to." ).PlaceHolder ("<port>" ).IntVar (& ctx .healthPort )
@@ -169,6 +168,8 @@ func registerServe(app *kingpin.Application) (*kingpin.CmdClause, *serveContext)
169168 serve .Flag ("leader-election-resource-namespace" , "The namespace of the resource (Lease) leader election will lease." ).Default (config .GetenvOr ("CONTOUR_NAMESPACE" , "projectcontour" )).StringVar (& ctx .LeaderElection .Namespace )
170169 serve .Flag ("leader-election-retry-period" , "The interval which Contour will attempt to acquire leadership lease." ).Default ("2s" ).DurationVar (& ctx .LeaderElection .RetryPeriod )
171170
171+ serve .Flag ("load-balancer-status" , "The source to inspect for load balancer status details." ).PlaceHolder ("<kind:ns/name|address>" ).StringVar (& ctx .Config .LoadBalancerStatus )
172+
172173 serve .Flag ("root-namespaces" , "Restrict contour to searching these namespaces for root ingress routes." ).PlaceHolder ("<ns,ns>" ).StringVar (& ctx .rootNamespaces )
173174
174175 serve .Flag ("stats-address" , "Envoy /stats interface address." ).PlaceHolder ("<ipaddr>" ).StringVar (& ctx .statsAddr )
@@ -686,48 +687,84 @@ func (s *Server) doServe() error {
686687 return err
687688 }
688689
689- // Register an informer to watch envoy's service if we haven't been given static details.
690- if lbAddress := contourConfiguration .Ingress .StatusAddress ; len (lbAddress ) > 0 {
691- s .log .WithField ("loadbalancer-address" , lbAddress ).Info ("Using supplied information for Ingress status" )
692- lbsw .lbStatus <- parseStatusFlag (lbAddress )
693- } else {
694- serviceHandler := & k8s.ServiceStatusLoadBalancerWatcher {
695- ServiceName : contourConfiguration .Envoy .Service .Name ,
696- LBStatus : lbsw .lbStatus ,
697- Log : s .log .WithField ("context" , "serviceStatusLoadBalancerWatcher" ),
690+ if contourConfiguration .Envoy .LoadBalancer != "" {
691+ if contourConfiguration .Ingress .StatusAddress != "" {
692+ s .log .Warnf ("ingress-status-address is ignored when load-balancer-status is specified" )
698693 }
699-
700- var handler cache.ResourceEventHandler = serviceHandler
701- if contourConfiguration .Envoy .Service .Namespace != "" {
702- handler = k8s .NewNamespaceFilter ([]string {contourConfiguration .Envoy .Service .Namespace }, handler )
694+ if contourConfiguration .Envoy .Service .Name != "" || contourConfiguration .Envoy .Service .Namespace != "" {
695+ s .log .Warnf ("envoy-service-name/envoy-service-namespace are ignored when load-balancer-status is specified" )
703696 }
704697
705- if err := s .informOnResource (& corev1.Service {}, handler ); err != nil {
706- s .log .WithError (err ).WithField ("resource" , "services" ).Fatal ("failed to create informer" )
698+ elbs , err := parseEnvoyLoadBalancerStatus (contourConfiguration .Envoy .LoadBalancer )
699+ if err != nil {
700+ return err
707701 }
708702
709- ingressHandler := & k8s.IngressStatusLoadBalancerWatcher {
710- ServiceName : contourConfiguration .Envoy .Service .Name ,
711- LBStatus : lbsw .lbStatus ,
712- Log : s .log .WithField ("context" , "ingressStatusLoadBalancerWatcher" ),
713- }
703+ switch strings .ToLower (elbs .Kind ) {
704+ case "hostname" :
705+ s .log .WithField ("loadbalancer-fqdns" , lbAddress ).Info ("Using supplied information for Ingress status" )
706+ lbsw .lbStatus <- parseStatusFlag (elbs .FQDNs )
707+ case "service" :
708+ serviceHandler := & k8s.ServiceStatusLoadBalancerWatcher {
709+ ServiceName : elbs .Name ,
710+ LBStatus : lbsw .lbStatus ,
711+ Log : s .log .WithField ("context" , "serviceStatusLoadBalancerWatcher" ),
712+ }
714713
715- var ingressEventHandler cache.ResourceEventHandler = ingressHandler
716- if contourConfiguration . Envoy . Ingress .Namespace != "" {
717- handler = k8s .NewNamespaceFilter ([]string {contourConfiguration . Envoy . Ingress .Namespace }, handler )
718- }
714+ var handler cache.ResourceEventHandler = serviceHandler
715+ if elbs .Namespace != "" {
716+ handler = k8s .NewNamespaceFilter ([]string {elbs .Namespace }, handler )
717+ }
719718
720- if err := informOnResource (& networking_v1.Ingress {}, ingressEventHandler , s .mgr .GetCache ()); err != nil {
721- s .log .WithError (err ).WithField ("resource" , "ingresses" ).Fatal ("failed to create ingresses informer" )
719+ if err := s .informOnResource (& corev1.Service {}, handler ); err != nil {
720+ s .log .WithError (err ).WithField ("resource" , "services" ).Fatal ("failed to create services informer" )
721+ }
722+ s .log .Infof ("Watching %s for Ingress status" , elbs )
723+ case "ingress" :
724+ ingressHandler := & k8s.IngressStatusLoadBalancerWatcher {
725+ IngressName : elbs .Name ,
726+ LBStatus : lbsw .lbStatus ,
727+ Log : s .log .WithField ("context" , "ingressStatusLoadBalancerWatcher" ),
728+ }
729+
730+ var handler cache.ResourceEventHandler = ingressHandler
731+ if elbs .Namespace != "" {
732+ handler = k8s .NewNamespaceFilter ([]string {elbs .Namespace }, handler )
733+ }
734+
735+ if err := s .informOnResource (& networking_v1.Ingress {}, handler ); err != nil {
736+ s .log .WithError (err ).WithField ("resource" , "ingresses" ).Fatal ("failed to create ingresses informer" )
737+ }
738+ s .log .Infof ("Watching %s for Ingress status" , elbs )
739+ default :
740+ return fmt .Errorf ("unsupported ingress kind: %s" , elbs .Kind )
722741 }
723742
724- s .log .WithField ("envoy-service-name" , contourConfiguration .Envoy .Service .Name ).
725- WithField ("envoy-service-namespace" , contourConfiguration .Envoy .Service .Namespace ).
726- Info ("Watching Service for Ingress status" )
743+ } else {
744+ if lbAddress := contourConfiguration .Ingress .StatusAddress ; len (lbAddress ) > 0 {
745+ s .log .WithField ("loadbalancer-address" , lbAddress ).Info ("Using supplied information for Ingress status" )
746+ lbsw .lbStatus <- parseStatusFlag (lbAddress )
747+ } else {
748+ // Register an informer to watch envoy's service if we haven't been given static details.
749+ serviceHandler := & k8s.ServiceStatusLoadBalancerWatcher {
750+ ServiceName : contourConfiguration .Envoy .Service .Name ,
751+ LBStatus : lbsw .lbStatus ,
752+ Log : s .log .WithField ("context" , "serviceStatusLoadBalancerWatcher" ),
753+ }
727754
728- s .log .WithField ("envoy-ingress-name" , contourConfiguration .Envoy .Ingress .Name ).
729- WithField ("envoy-ingress-namespace" , contourConfiguration .Envoy .Ingress .Namespace ).
730- Info ("Watching Ingress for Ingress status" )
755+ var handler cache.ResourceEventHandler = serviceHandler
756+ if contourConfiguration .Envoy .Service .Namespace != "" {
757+ handler = k8s .NewNamespaceFilter ([]string {contourConfiguration .Envoy .Service .Namespace }, handler )
758+ }
759+
760+ if err := s .informOnResource (& corev1.Service {}, handler ); err != nil {
761+ s .log .WithError (err ).WithField ("resource" , "services" ).Fatal ("failed to create services informer" )
762+ }
763+
764+ s .log .WithField ("envoy-service-name" , contourConfiguration .Envoy .Service .Name ).
765+ WithField ("envoy-service-namespace" , contourConfiguration .Envoy .Service .Namespace ).
766+ Info ("Watching Service for Ingress status" )
767+ }
731768 }
732769
733770 xdsServer := & xdsServer {
@@ -756,6 +793,55 @@ func (s *Server) doServe() error {
756793 return s .mgr .Start (signals .SetupSignalHandler ())
757794}
758795
796+ type envoyLoadBalancerStatus struct {
797+ Kind string
798+ FQDNs string
799+ config.NamespacedName
800+ }
801+
802+ func (elbs * envoyLoadBalancerStatus ) String () string {
803+ if elbs .Kind == "hostname" {
804+ return fmt .Sprintf ("%s:%s" , elbs .Kind , elbs .FQDNs )
805+ }
806+ return fmt .Sprintf ("%s:%s/%s" , elbs .Kind , elbs .Namespace , elbs .Name )
807+ }
808+
809+ func parseEnvoyLoadBalancerStatus (s string ) (* envoyLoadBalancerStatus , error ) {
810+ parts := strings .SplitN (s , ":" , 2 )
811+ if len (parts ) != 2 {
812+ return nil , fmt .Errorf ("invalid load-balancer-status: %s" , s )
813+ }
814+
815+ if parts [1 ] == "" {
816+ return nil , fmt .Errorf ("invalid load-balancer-status: empty object reference" )
817+ }
818+
819+ elbs := envoyLoadBalancerStatus {}
820+
821+ elbs .Kind = strings .ToLower (parts [0 ])
822+ switch elbs .Kind {
823+ case "ingress" , "service" :
824+ parts = strings .Split (parts [1 ], "/" )
825+ if len (parts ) != 2 {
826+ return nil , fmt .Errorf ("invalid load-balancer-status: %s is not in the format of <namespace>/<name>" , s )
827+ }
828+
829+ if parts [0 ] == "" || parts [1 ] == "" {
830+ return nil , fmt .Errorf ("invalid load-balancer-status: <namespace> or <name> is empty" )
831+ }
832+ elbs .Namespace = parts [0 ]
833+ elbs .Name = parts [1 ]
834+ case "hostname" :
835+ elbs .FQDNs = parts [1 ]
836+ case "" :
837+ return nil , fmt .Errorf ("invalid load-balancer-status: kind is empty" )
838+ default :
839+ return nil , fmt .Errorf ("invalid load-balancer-status: unsupported kind: %s" , elbs .Kind )
840+ }
841+
842+ return & elbs , nil
843+ }
844+
759845func (s * Server ) getExtensionSvcConfig (name string , namespace string ) (xdscache_v3.ExtensionServiceConfig , error ) {
760846 extensionSvc := & contour_api_v1alpha1.ExtensionService {}
761847 key := client.ObjectKey {
0 commit comments