@@ -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,86 @@ 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+ // Register an informer to watch envoy's service/ingress if we haven't been given static details.
704+ if lbAddress := elbs .FQDNs ; len (lbAddress ) > 0 {
705+ s .log .WithField ("loadbalancer-fqdns" , lbAddress ).Info ("Using supplied information for Ingress status" )
706+ lbsw .lbStatus <- parseStatusFlag (lbAddress )
707+ } else {
708+ switch strings .ToLower (elbs .Kind ) {
709+ case "service" :
710+ serviceHandler := & k8s.ServiceStatusLoadBalancerWatcher {
711+ ServiceName : elbs .Name ,
712+ LBStatus : lbsw .lbStatus ,
713+ Log : s .log .WithField ("context" , "serviceStatusLoadBalancerWatcher" ),
714+ }
714715
715- var ingressEventHandler cache.ResourceEventHandler = ingressHandler
716- if contourConfiguration . Envoy . Ingress .Namespace != "" {
717- handler = k8s .NewNamespaceFilter ([]string {contourConfiguration . Envoy . Ingress .Namespace }, handler )
718- }
716+ var handler cache.ResourceEventHandler = serviceHandler
717+ if elbs .Namespace != "" {
718+ handler = k8s .NewNamespaceFilter ([]string {elbs .Namespace }, handler )
719+ }
719720
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" )
721+ if err := s .informOnResource (& corev1.Service {}, handler ); err != nil {
722+ s .log .WithError (err ).WithField ("resource" , "services" ).Fatal ("failed to create services informer" )
723+ }
724+ case "ingress" :
725+ ingressHandler := & k8s.IngressStatusLoadBalancerWatcher {
726+ IngressName : elbs .Name ,
727+ LBStatus : lbsw .lbStatus ,
728+ Log : s .log .WithField ("context" , "ingressStatusLoadBalancerWatcher" ),
729+ }
730+
731+ var handler cache.ResourceEventHandler = ingressHandler
732+ if elbs .Namespace != "" {
733+ handler = k8s .NewNamespaceFilter ([]string {elbs .Namespace }, handler )
734+ }
735+
736+ if err := s .informOnResource (& networking_v1.Ingress {}, handler ); err != nil {
737+ s .log .WithError (err ).WithField ("resource" , "ingresses" ).Fatal ("failed to create ingresses informer" )
738+ }
739+ default :
740+ return fmt .Errorf ("unsupported ingress kind: %s" , elbs .Kind )
741+ }
742+
743+ s .log .Infof ("Watching %s for Ingress status" , elbs )
722744 }
745+ } else {
746+ // Register an informer to watch envoy's service/ingress if we haven't been given static details.
747+ if lbAddress := contourConfiguration .Ingress .StatusAddress ; len (lbAddress ) > 0 {
748+ s .log .WithField ("loadbalancer-address" , lbAddress ).Info ("Using supplied information for Ingress status" )
749+ lbsw .lbStatus <- parseStatusFlag (lbAddress )
750+ } else {
751+ serviceHandler := & k8s.ServiceStatusLoadBalancerWatcher {
752+ ServiceName : contourConfiguration .Envoy .Service .Name ,
753+ LBStatus : lbsw .lbStatus ,
754+ Log : s .log .WithField ("context" , "serviceStatusLoadBalancerWatcher" ),
755+ }
723756
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" )
757+ var handler cache.ResourceEventHandler = serviceHandler
758+ if contourConfiguration .Envoy .Service .Namespace != "" {
759+ handler = k8s .NewNamespaceFilter ([]string {contourConfiguration .Envoy .Service .Namespace }, handler )
760+ }
727761
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" )
762+ if err := s .informOnResource (& corev1.Service {}, handler ); err != nil {
763+ s .log .WithError (err ).WithField ("resource" , "services" ).Fatal ("failed to create services informer" )
764+ }
765+
766+ s .log .WithField ("envoy-service-name" , contourConfiguration .Envoy .Service .Name ).
767+ WithField ("envoy-service-namespace" , contourConfiguration .Envoy .Service .Namespace ).
768+ Info ("Watching Service for Ingress status" )
769+ }
731770 }
732771
733772 xdsServer := & xdsServer {
@@ -756,6 +795,55 @@ func (s *Server) doServe() error {
756795 return s .mgr .Start (signals .SetupSignalHandler ())
757796}
758797
798+ type envoyLoadBalancerStatus struct {
799+ Kind string
800+ FQDNs string
801+ config.NamespacedName
802+ }
803+
804+ func (elbs * envoyLoadBalancerStatus ) String () string {
805+ if elbs .Kind == "hostname" {
806+ return fmt .Sprintf ("%s:%s" , elbs .Kind , elbs .FQDNs )
807+ }
808+ return fmt .Sprintf ("%s:%s/%s" , elbs .Kind , elbs .Namespace , elbs .Name )
809+ }
810+
811+ func parseEnvoyLoadBalancerStatus (s string ) (* envoyLoadBalancerStatus , error ) {
812+ parts := strings .SplitN (s , ":" , 2 )
813+ if len (parts ) != 2 {
814+ return nil , fmt .Errorf ("invalid load-balancer-status: %s" , s )
815+ }
816+
817+ if parts [1 ] == "" {
818+ return nil , fmt .Errorf ("invalid load-balancer-status: empty object reference" )
819+ }
820+
821+ elbs := envoyLoadBalancerStatus {}
822+
823+ elbs .Kind = strings .ToLower (parts [0 ])
824+ switch elbs .Kind {
825+ case "ingress" , "service" :
826+ parts = strings .Split (parts [1 ], "/" )
827+ if len (parts ) != 2 {
828+ return nil , fmt .Errorf ("invalid load-balancer-status: %s is not in the format of <namespace>/<name>" , s )
829+ }
830+
831+ if parts [0 ] == "" || parts [1 ] == "" {
832+ return nil , fmt .Errorf ("invalid load-balancer-status: <namespace> or <name> is empty" )
833+ }
834+ elbs .Namespace = parts [0 ]
835+ elbs .Name = parts [1 ]
836+ case "hostname" :
837+ elbs .FQDNs = parts [1 ]
838+ case "" :
839+ return nil , fmt .Errorf ("invalid load-balancer-status: kind is empty" )
840+ default :
841+ return nil , fmt .Errorf ("invalid load-balancer-status: unsupported kind: %s" , elbs .Kind )
842+ }
843+
844+ return & elbs , nil
845+ }
846+
759847func (s * Server ) getExtensionSvcConfig (name string , namespace string ) (xdscache_v3.ExtensionServiceConfig , error ) {
760848 extensionSvc := & contour_api_v1alpha1.ExtensionService {}
761849 key := client.ObjectKey {
0 commit comments