@@ -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" , "Address to set or the source to inspect for ingress status." ).PlaceHolder ("<kind:namespace/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 )
@@ -673,87 +674,162 @@ func (s *Server) doServe() error {
673674 }
674675
675676 // Set up ingress load balancer status writer.
677+ if err := s .setupIngressLoadBalancerStatusWriter (contourConfiguration , ingressClassNames , gatewayControllerName , gatewayRef , sh .Writer ()); err != nil {
678+ return err
679+ }
680+
681+ xdsServer := & xdsServer {
682+ log : s .log ,
683+ registry : s .registry ,
684+ config : * contourConfiguration .XDSServer ,
685+ snapshotHandler : snapshotHandler ,
686+ resources : resources ,
687+ initialDagBuilt : contourHandler .HasBuiltInitialDag ,
688+ }
689+ if err := s .mgr .Add (xdsServer ); err != nil {
690+ return err
691+ }
692+
693+ notifier := & leadership.Notifier {
694+ ToNotify : append ([]leadership.NeedLeaderElectionNotification {
695+ contourHandler ,
696+ observer ,
697+ }, needsNotification ... ),
698+ }
699+ if err := s .mgr .Add (notifier ); err != nil {
700+ return err
701+ }
702+
703+ // GO!
704+ return s .mgr .Start (signals .SetupSignalHandler ())
705+ }
706+
707+ func (s * Server ) setupIngressLoadBalancerStatusWriter (
708+ contourConfiguration contour_api_v1alpha1.ContourConfigurationSpec ,
709+ ingressClassNames []string ,
710+ gatewayControllerName string ,
711+ gatewayRef * types.NamespacedName ,
712+ statusUpdater k8s.StatusUpdater ) error {
676713 lbsw := & loadBalancerStatusWriter {
677714 log : s .log .WithField ("context" , "loadBalancerStatusWriter" ),
678715 cache : s .mgr .GetCache (),
679716 lbStatus : make (chan corev1.LoadBalancerStatus , 1 ),
680717 ingressClassNames : ingressClassNames ,
681718 gatewayControllerName : gatewayControllerName ,
682719 gatewayRef : gatewayRef ,
683- statusUpdater : sh . Writer () ,
720+ statusUpdater : statusUpdater ,
684721 }
685722 if err := s .mgr .Add (lbsw ); err != nil {
686723 return err
687724 }
688725
689- // Register an informer to watch envoy's service if we haven't been given static details.
726+ elbs := & envoyLoadBalancerStatus {}
690727 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 )
728+ elbs .Kind = "hostname"
729+ elbs .FQDNs = lbAddress
730+ } else if contourConfiguration .Envoy .LoadBalancer != "" {
731+ status , err := parseEnvoyLoadBalancerStatus (contourConfiguration .Envoy .LoadBalancer )
732+ if err != nil {
733+ return err
734+ }
735+ elbs = status
693736 } else {
737+ elbs .Kind = "service"
738+ elbs .Namespace = contourConfiguration .Envoy .Service .Namespace
739+ elbs .Name = contourConfiguration .Envoy .Service .Name
740+ }
741+ switch strings .ToLower (elbs .Kind ) {
742+ case "hostname" :
743+ s .log .WithField ("loadbalancer-fqdns" , lbAddress ).Info ("Using supplied hostname for Ingress status" )
744+ lbsw .lbStatus <- parseStatusFlag (elbs .FQDNs )
745+ case "service" :
746+ // Register an informer to watch supplied service
694747 serviceHandler := & k8s.ServiceStatusLoadBalancerWatcher {
695- ServiceName : contourConfiguration . Envoy . Service .Name ,
748+ ServiceName : elbs .Name ,
696749 LBStatus : lbsw .lbStatus ,
697750 Log : s .log .WithField ("context" , "serviceStatusLoadBalancerWatcher" ),
698751 }
699752
700753 var handler cache.ResourceEventHandler = serviceHandler
701- if contourConfiguration . Envoy . Service .Namespace != "" {
702- handler = k8s .NewNamespaceFilter ([]string {contourConfiguration . Envoy . Service .Namespace }, handler )
754+ if elbs .Namespace != "" {
755+ handler = k8s .NewNamespaceFilter ([]string {elbs .Namespace }, handler )
703756 }
704757
705758 if err := s .informOnResource (& corev1.Service {}, handler ); err != nil {
706- s .log .WithError (err ).WithField ("resource" , "services" ).Fatal ("failed to create informer" )
759+ s .log .WithError (err ).WithField ("resource" , "services" ).Fatal ("failed to create services informer" )
707760 }
708-
761+ s .log .Infof ("Watching %s for Ingress status" , elbs )
762+ case "ingress" :
763+ // Register an informer to watch supplied ingress
709764 ingressHandler := & k8s.IngressStatusLoadBalancerWatcher {
710- ServiceName : contourConfiguration . Envoy . Service .Name ,
765+ IngressName : elbs .Name ,
711766 LBStatus : lbsw .lbStatus ,
712767 Log : s .log .WithField ("context" , "ingressStatusLoadBalancerWatcher" ),
713768 }
714769
715- var ingressEventHandler cache.ResourceEventHandler = ingressHandler
716- if contourConfiguration . Envoy . Ingress .Namespace != "" {
717- handler = k8s .NewNamespaceFilter ([]string {contourConfiguration . Envoy . Ingress .Namespace }, handler )
770+ var handler cache.ResourceEventHandler = ingressHandler
771+ if elbs .Namespace != "" {
772+ handler = k8s .NewNamespaceFilter ([]string {elbs .Namespace }, handler )
718773 }
719774
720- if err := informOnResource (& networking_v1.Ingress {}, ingressEventHandler , s . mgr . GetCache () ); err != nil {
775+ if err := s . informOnResource (& networking_v1.Ingress {}, handler ); err != nil {
721776 s .log .WithError (err ).WithField ("resource" , "ingresses" ).Fatal ("failed to create ingresses informer" )
722777 }
778+ s .log .Infof ("Watching %s for Ingress status" , elbs )
779+ default :
780+ return fmt .Errorf ("unsupported ingress kind: %s" , elbs .Kind )
781+ }
723782
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" )
783+ return nil
784+ }
727785
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" )
731- }
786+ type envoyLoadBalancerStatus struct {
787+ Kind string
788+ FQDNs string
789+ config.NamespacedName
790+ }
732791
733- xdsServer := & xdsServer {
734- log : s .log ,
735- registry : s .registry ,
736- config : * contourConfiguration .XDSServer ,
737- snapshotHandler : snapshotHandler ,
738- resources : resources ,
739- initialDagBuilt : contourHandler .HasBuiltInitialDag ,
792+ func (elbs * envoyLoadBalancerStatus ) String () string {
793+ if elbs .Kind == "hostname" {
794+ return fmt .Sprintf ("%s:%s" , elbs .Kind , elbs .FQDNs )
740795 }
741- if err := s .mgr .Add (xdsServer ); err != nil {
742- return err
796+ return fmt .Sprintf ("%s:%s/%s" , elbs .Kind , elbs .Namespace , elbs .Name )
797+ }
798+
799+ func parseEnvoyLoadBalancerStatus (s string ) (* envoyLoadBalancerStatus , error ) {
800+ parts := strings .SplitN (s , ":" , 2 )
801+ if len (parts ) != 2 {
802+ return nil , fmt .Errorf ("invalid load-balancer-status: %s" , s )
743803 }
744804
745- notifier := & leadership.Notifier {
746- ToNotify : append ([]leadership.NeedLeaderElectionNotification {
747- contourHandler ,
748- observer ,
749- }, needsNotification ... ),
805+ if parts [1 ] == "" {
806+ return nil , fmt .Errorf ("invalid load-balancer-status: empty object reference" )
750807 }
751- if err := s .mgr .Add (notifier ); err != nil {
752- return err
808+
809+ elbs := envoyLoadBalancerStatus {}
810+
811+ elbs .Kind = strings .ToLower (parts [0 ])
812+ switch elbs .Kind {
813+ case "ingress" , "service" :
814+ parts = strings .Split (parts [1 ], "/" )
815+ if len (parts ) != 2 {
816+ return nil , fmt .Errorf ("invalid load-balancer-status: %s is not in the format of <namespace>/<name>" , s )
817+ }
818+
819+ if parts [0 ] == "" || parts [1 ] == "" {
820+ return nil , fmt .Errorf ("invalid load-balancer-status: <namespace> or <name> is empty" )
821+ }
822+ elbs .Namespace = parts [0 ]
823+ elbs .Name = parts [1 ]
824+ case "hostname" :
825+ elbs .FQDNs = parts [1 ]
826+ case "" :
827+ return nil , fmt .Errorf ("invalid load-balancer-status: kind is empty" )
828+ default :
829+ return nil , fmt .Errorf ("invalid load-balancer-status: unsupported kind: %s" , elbs .Kind )
753830 }
754831
755- // GO!
756- return s .mgr .Start (signals .SetupSignalHandler ())
832+ return & elbs , nil
757833}
758834
759835func (s * Server ) getExtensionSvcConfig (name string , namespace string ) (xdscache_v3.ExtensionServiceConfig , error ) {
0 commit comments