@@ -38,6 +38,7 @@ type SvcContext struct {
3838 service * store.Service
3939 backend * models.Backend
4040 certs * haproxy.Certificates
41+ modeTCP bool
4142 newBackend bool
4243}
4344
@@ -46,20 +47,13 @@ func NewCtx(k8s store.K8s, ingress *store.Ingress, path *store.IngressPath, cert
4647 if err != nil {
4748 return nil , err
4849 }
49- backend := models.Backend {
50- Mode : "http" ,
51- DefaultServer : & models.DefaultServer {},
52- }
53- if tcpService {
54- backend .Mode = "tcp"
55- }
5650 return & SvcContext {
5751 store : k8s ,
5852 ingress : ingress ,
5953 path : path ,
6054 service : service ,
61- backend : & backend ,
6255 certs : certs ,
56+ modeTCP : tcpService ,
6357 }, nil
6458}
6559
@@ -77,11 +71,12 @@ func (s *SvcContext) GetService() *store.Service {
7771 return s .service
7872}
7973
80- // setBackendName checks if servicePort provided in IngressPath exists and construct corresponding backend name
74+ // GetBackendName checks if servicePort provided in IngressPath exists and construct corresponding backend name
8175// Backend name is in format "ServiceNS-ServiceName-PortName"
82- func (s * SvcContext ) setBackendName () error {
83- if s .backend .Name != "" {
84- return nil
76+ func (s * SvcContext ) GetBackendName () (name string , err error ) {
77+ if s .backend != nil && s .backend .Name != "" {
78+ name = s .backend .Name
79+ return
8580 }
8681 var svcPort store.ServicePort
8782 found := false
@@ -95,61 +90,91 @@ func (s *SvcContext) setBackendName() error {
9590 }
9691 if ! found {
9792 if s .path .SvcPortString != "" {
98- return fmt .Errorf ("service %s: no service port matching '%s'" , s .service .Name , s .path .SvcPortString )
93+ err = fmt .Errorf ("service %s: no service port matching '%s'" , s .service .Name , s .path .SvcPortString )
94+ } else {
95+ err = fmt .Errorf ("service %s: no service port matching '%d'" , s .service .Name , s .path .SvcPortInt )
9996 }
100- return fmt . Errorf ( "service %s: no service port matching '%d'" , s . service . Name , s . path . SvcPortInt )
97+ return
10198 }
10299 s .path .SvcPortResolved = & svcPort
103100 if svcPort .Name != "" {
104- s . backend . Name = fmt .Sprintf ("%s-%s-%s" , s .service .Namespace , s .service .Name , svcPort .Name )
101+ name = fmt .Sprintf ("%s-%s-%s" , s .service .Namespace , s .service .Name , svcPort .Name )
105102 } else {
106- s . backend . Name = fmt .Sprintf ("%s-%s-%s" , s .service .Namespace , s .service .Name , strconv .Itoa (int (svcPort .Port )))
103+ name = fmt .Sprintf ("%s-%s-%s" , s .service .Namespace , s .service .Name , strconv .Itoa (int (svcPort .Port )))
107104 }
108- return nil
105+ return
109106}
110107
111108// HandleBackend processes a Service Context and creates/updates corresponding backend configuration in HAProxy
112- func (s * SvcContext ) HandleBackend (client api.HAProxyClient , store store.K8s ) (backend * models.Backend , reload bool , err error ) {
113- backend = s .backend
114- if err = s .setBackendName (); err != nil {
109+ func (s * SvcContext ) HandleBackend (client api.HAProxyClient , store store.K8s ) (reload bool , err error ) {
110+ var backend , newBackend * models.Backend
111+ newBackend , err = s .getBackendModel (store )
112+ s .backend = newBackend
113+ if err != nil {
115114 return
116115 }
117116 // Get/Create Backend
118- if s .service .DNS != "" {
119- backend .DefaultServer = & models.DefaultServer {InitAddr : "last,libc,none" }
120- }
121- var oldBackend * models.Backend
122- oldBackend , err = client .BackendGet (s .backend .Name )
123- if err != nil {
124- if err = client .BackendCreate (* backend ); err != nil {
117+ backend , err = client .BackendGet (newBackend .Name )
118+ if err == nil {
119+ // Update Backend
120+ result := deep .Equal (newBackend , backend )
121+ if len (result ) != 0 {
122+ if err = client .BackendEdit (* newBackend ); err != nil {
123+ return
124+ }
125+ reload = true
126+ logger .Debugf ("Ingress '%s/%s': backend '%s' updated: %s\n Reload required" , s .ingress .Namespace , s .ingress .Name , newBackend .Name , result )
127+ }
128+ } else {
129+ if err = client .BackendCreate (* newBackend ); err != nil {
125130 return
126131 }
127132 s .newBackend = true
128133 reload = true
129- logger .Debugf ("Ingress '%s/%s': new backend '%s', reload required" , s .ingress .Namespace , s .ingress .Name , backend .Name )
134+ logger .Debugf ("Ingress '%s/%s': new backend '%s', reload required" , s .ingress .Namespace , s .ingress .Name , newBackend .Name )
135+ }
136+ // config-snippet
137+ change , errSnipp := annotations .UpdateBackendCfgSnippet (client , newBackend .Name )
138+ logger .Error (errSnipp )
139+ if len (change ) != 0 {
140+ reload = true
141+ logger .Debugf ("Ingress '%s/%s': backend '%s' updated: %s\n Reload required" , s .ingress .Namespace , s .ingress .Name , newBackend .Name , change )
142+ }
143+ return
144+ }
145+
146+ // getBackendModel checks for a corresponding custom resource before falling back to annoations
147+ func (s * SvcContext ) getBackendModel (store store.K8s ) (* models.Backend , error ) {
148+ var backend * models.Backend
149+ var err error
150+ crInuse := true
151+ backend , err = annotations .ModelBackend ("cr-backend" , s .service .Namespace , store , s .service .Annotations , s .ingress .Annotations , store .ConfigMaps .Main .Annotations )
152+ logger .Warning (err )
153+ if backend == nil {
154+ backend = & models.Backend {DefaultServer : & models.DefaultServer {}}
155+ crInuse = false
156+ }
157+ if s .modeTCP {
158+ backend .Mode = "tcp"
159+ } else {
160+ backend .Mode = "http"
161+ }
162+ if backend .Name , err = s .GetBackendName (); err != nil {
163+ return nil , err
164+ }
165+ if s .service .DNS != "" {
166+ backend .DefaultServer = & models.DefaultServer {InitAddr : "last,libc,none" }
167+ }
168+ if crInuse {
169+ return backend , nil
130170 }
131171 for _ , a := range annotations .Backend (backend , store , s .certs ) {
132172 err = a .Process (store , s .service .Annotations , s .ingress .Annotations , store .ConfigMaps .Main .Annotations )
133173 if err != nil {
134174 logger .Errorf ("service '%s/%s': annotation '%s': %s" , s .service .Namespace , s .service .Name , a .GetName (), err )
135175 }
136176 }
137- // Update Backend
138- result := deep .Equal (oldBackend , backend )
139- if len (result ) != 0 {
140- if err = client .BackendEdit (* backend ); err != nil {
141- return
142- }
143- reload = true
144- logger .Debugf ("Ingress '%s/%s': backend '%s' updated: %s\n Reload required" , s .ingress .Namespace , s .ingress .Name , backend .Name , result )
145- }
146- change , errSnipp := annotations .UpdateBackendCfgSnippet (client , backend .Name )
147- logger .Error (errSnipp )
148- if len (change ) != 0 {
149- reload = true
150- logger .Debugf ("Ingress '%s/%s': backend '%s' updated: %s\n Reload required" , s .ingress .Namespace , s .ingress .Name , backend .Name , change )
151- }
152- return
177+ return backend , nil
153178}
154179
155180func getService (k8s store.K8s , namespace , name string ) (* store.Service , error ) {
0 commit comments