diff --git a/consul/config.go b/consul/config.go index 0781168..62ebff6 100644 --- a/consul/config.go +++ b/consul/config.go @@ -18,6 +18,7 @@ type Upstream struct { Service string LocalBindAddress string LocalBindPort int + Protocol string TLS @@ -47,6 +48,7 @@ func (n UpstreamNode) Equal(o UpstreamNode) bool { type Downstream struct { LocalBindAddress string LocalBindPort int + Protocol string TargetAddress string TargetPort int diff --git a/consul/watcher.go b/consul/watcher.go index a341375..ab7b343 100644 --- a/consul/watcher.go +++ b/consul/watcher.go @@ -21,6 +21,7 @@ type upstream struct { LocalBindPort int Service string Datacenter string + Protocol string Nodes []*api.ServiceEntry done bool @@ -29,6 +30,7 @@ type upstream struct { type downstream struct { LocalBindAddress string LocalBindPort int + Protocol string TargetAddress string TargetPort int } @@ -111,6 +113,13 @@ func (w *Watcher) handleProxyChange(first bool, srv *api.AgentService) { w.downstream.LocalBindAddress = defaultDownstreamBindAddr w.downstream.LocalBindPort = srv.Port w.downstream.TargetAddress = defaultUpstreamBindAddr + + if srv.Proxy != nil && srv.Proxy.Config != nil { + if c, ok := srv.Proxy.Config["protocol"].(string); ok { + w.downstream.Protocol = c + } + } + if srv.Connect != nil && srv.Connect.SidecarService != nil && srv.Connect.SidecarService.Proxy != nil && srv.Connect.SidecarService.Proxy.Config != nil { if b, ok := srv.Connect.SidecarService.Proxy.Config["bind_address"].(string); ok { w.downstream.LocalBindAddress = b @@ -155,6 +164,12 @@ func (w *Watcher) startUpstream(up api.Upstream) { Datacenter: up.Datacenter, } + if up.Config["protocol"] != nil { + if p, ok := up.Config["protocol"].(string); ok { + u.Protocol = p + } + } + w.lock.Lock() w.upstreams[up.DestinationName] = u w.lock.Unlock() @@ -332,7 +347,7 @@ func (w *Watcher) genCfg() Config { LocalBindPort: w.downstream.LocalBindPort, TargetAddress: w.downstream.TargetAddress, TargetPort: w.downstream.TargetPort, - + Protocol: w.downstream.Protocol, TLS: TLS{ CAs: w.certCAs, Cert: w.leaf.Cert, @@ -346,14 +361,13 @@ func (w *Watcher) genCfg() Config { Service: up.Service, LocalBindAddress: up.LocalBindAddress, LocalBindPort: up.LocalBindPort, - + Protocol: up.Protocol, TLS: TLS{ CAs: w.certCAs, Cert: w.leaf.Cert, Key: w.leaf.Key, }, } - for _, s := range up.Nodes { serviceInstancesTotal++ host := s.Service.Address diff --git a/haproxy/state/downstream.go b/haproxy/state/downstream.go index f66de69..b13b4d7 100644 --- a/haproxy/state/downstream.go +++ b/haproxy/state/downstream.go @@ -10,19 +10,26 @@ import ( func generateDownstream(opts Options, certStore CertificateStore, cfg consul.Downstream, state State) (State, error) { feName := "front_downstream" beName := "back_downstream" + feMode := models.FrontendModeHTTP + beMode := models.BackendModeHTTP caPath, crtPath, err := certStore.CertsPath(cfg.TLS) if err != nil { return state, err } + if cfg.Protocol != "" && cfg.Protocol == "tcp" { + feMode = models.FrontendModeTCP + beMode = models.BackendModeTCP + } + // Main config fe := Frontend{ Frontend: models.Frontend{ Name: feName, DefaultBackend: beName, ClientTimeout: &clientTimeout, - Mode: models.FrontendModeHTTP, + Mode: feMode, Httplog: opts.LogRequests, }, Bind: models.Bind{ @@ -73,7 +80,7 @@ func generateDownstream(opts Options, certStore CertificateStore, cfg consul.Dow Name: beName, ServerTimeout: &serverTimeout, ConnectTimeout: &connectTimeout, - Mode: models.BackendModeHTTP, + Mode: beMode, }, Servers: []models.Server{ models.Server{ diff --git a/haproxy/state/upstream.go b/haproxy/state/upstream.go index 4ded654..f8ee6bd 100644 --- a/haproxy/state/upstream.go +++ b/haproxy/state/upstream.go @@ -10,14 +10,22 @@ import ( func generateUpstream(opts Options, certStore CertificateStore, cfg consul.Upstream, oldState, newState State) (State, error) { feName := fmt.Sprintf("front_%s", cfg.Service) beName := fmt.Sprintf("back_%s", cfg.Service) + feMode := models.FrontendModeHTTP + beMode := models.BackendModeHTTP fePort64 := int64(cfg.LocalBindPort) + + if cfg.Protocol != "" && cfg.Protocol == "tcp" { + feMode = models.FrontendModeTCP + beMode = models.BackendModeTCP + } + fe := Frontend{ Frontend: models.Frontend{ Name: feName, DefaultBackend: beName, ClientTimeout: &clientTimeout, - Mode: models.FrontendModeHTTP, + Mode: feMode, Httplog: opts.LogRequests, }, Bind: models.Bind{ @@ -45,7 +53,7 @@ func generateUpstream(opts Options, certStore CertificateStore, cfg consul.Upstr Balance: &models.Balance{ Algorithm: models.BalanceAlgorithmLeastconn, }, - Mode: models.BackendModeHTTP, + Mode: beMode, }, } if opts.LogRequests && opts.LogSocket != "" {