github.com/adityamillind98/nomad@v0.11.8/command/agent/consul/connect.go (about) 1 package consul 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/consul/api" 7 "github.com/hashicorp/nomad/helper" 8 "github.com/hashicorp/nomad/nomad/structs" 9 ) 10 11 // newConnect creates a new Consul AgentServiceConnect struct based on a Nomad 12 // Connect struct. If the nomad Connect struct is nil, nil will be returned to 13 // disable Connect for this service. 14 func newConnect(serviceName string, nc *structs.ConsulConnect, networks structs.Networks) (*api.AgentServiceConnect, error) { 15 if nc == nil { 16 // no connect stanza means there is no connect service to register 17 return nil, nil 18 } 19 20 if nc.Native { 21 return &api.AgentServiceConnect{Native: true}, nil 22 } 23 24 sidecarReg, err := connectSidecarRegistration(serviceName, nc.SidecarService, networks) 25 if err != nil { 26 return nil, err 27 } 28 29 return &api.AgentServiceConnect{ 30 Native: false, 31 SidecarService: sidecarReg, 32 }, nil 33 } 34 35 func connectSidecarRegistration(serviceName string, css *structs.ConsulSidecarService, networks structs.Networks) (*api.AgentServiceRegistration, error) { 36 if css == nil { 37 // no sidecar stanza means there is no sidecar service to register 38 return nil, nil 39 } 40 41 cNet, cPort, err := connectPort(serviceName, networks) 42 if err != nil { 43 return nil, err 44 } 45 46 proxy, err := connectProxy(css.Proxy, cPort.To, networks) 47 if err != nil { 48 return nil, err 49 } 50 51 return &api.AgentServiceRegistration{ 52 Tags: helper.CopySliceString(css.Tags), 53 Port: cPort.Value, 54 Address: cNet.IP, 55 Proxy: proxy, 56 }, nil 57 } 58 59 func connectProxy(proxy *structs.ConsulProxy, cPort int, networks structs.Networks) (*api.AgentServiceConnectProxyConfig, error) { 60 if proxy == nil { 61 proxy = new(structs.ConsulProxy) 62 } 63 64 expose, err := connectProxyExpose(proxy.Expose, networks) 65 if err != nil { 66 return nil, err 67 } 68 69 return &api.AgentServiceConnectProxyConfig{ 70 LocalServiceAddress: proxy.LocalServiceAddress, 71 LocalServicePort: proxy.LocalServicePort, 72 Config: connectProxyConfig(proxy.Config, cPort), 73 Upstreams: connectUpstreams(proxy.Upstreams), 74 Expose: expose, 75 }, nil 76 } 77 78 func connectProxyExpose(expose *structs.ConsulExposeConfig, networks structs.Networks) (api.ExposeConfig, error) { 79 if expose == nil { 80 return api.ExposeConfig{}, nil 81 } 82 83 paths, err := connectProxyExposePaths(expose.Paths, networks) 84 if err != nil { 85 return api.ExposeConfig{}, err 86 } 87 88 return api.ExposeConfig{ 89 Checks: false, 90 Paths: paths, 91 }, nil 92 } 93 94 func connectProxyExposePaths(in []structs.ConsulExposePath, networks structs.Networks) ([]api.ExposePath, error) { 95 if len(in) == 0 { 96 return nil, nil 97 } 98 99 paths := make([]api.ExposePath, len(in)) 100 for i, path := range in { 101 if _, exposedPort, err := connectExposePathPort(path.ListenerPort, networks); err != nil { 102 return nil, err 103 } else { 104 paths[i] = api.ExposePath{ 105 ListenerPort: exposedPort, 106 Path: path.Path, 107 LocalPathPort: path.LocalPathPort, 108 Protocol: path.Protocol, 109 ParsedFromCheck: false, 110 } 111 } 112 } 113 return paths, nil 114 } 115 116 func connectUpstreams(in []structs.ConsulUpstream) []api.Upstream { 117 if len(in) == 0 { 118 return nil 119 } 120 121 upstreams := make([]api.Upstream, len(in)) 122 for i, upstream := range in { 123 upstreams[i] = api.Upstream{ 124 DestinationName: upstream.DestinationName, 125 LocalBindPort: upstream.LocalBindPort, 126 } 127 } 128 return upstreams 129 } 130 131 func connectProxyConfig(cfg map[string]interface{}, port int) map[string]interface{} { 132 if cfg == nil { 133 cfg = make(map[string]interface{}) 134 } 135 cfg["bind_address"] = "0.0.0.0" 136 cfg["bind_port"] = port 137 return cfg 138 } 139 140 func connectNetworkInvariants(networks structs.Networks) error { 141 if n := len(networks); n != 1 { 142 return fmt.Errorf("Connect only supported with exactly 1 network (found %d)", n) 143 } 144 return nil 145 } 146 147 // connectPort returns the network and port for the Connect proxy sidecar 148 // defined for this service. An error is returned if the network and port 149 // cannot be determined. 150 func connectPort(serviceName string, networks structs.Networks) (*structs.NetworkResource, structs.Port, error) { 151 if err := connectNetworkInvariants(networks); err != nil { 152 return nil, structs.Port{}, err 153 } 154 155 port, ok := networks[0].PortForService(serviceName) 156 if !ok { 157 return nil, structs.Port{}, fmt.Errorf("No Connect port defined for service %q", serviceName) 158 } 159 160 return networks[0], port, nil 161 } 162 163 // connectExposePathPort returns the port for the exposed path for the exposed 164 // proxy path. 165 func connectExposePathPort(portLabel string, networks structs.Networks) (string, int, error) { 166 if err := connectNetworkInvariants(networks); err != nil { 167 return "", 0, err 168 } 169 170 ip, port := networks.Port(portLabel) 171 if port == 0 { 172 return "", 0, fmt.Errorf("No port of label %q defined", portLabel) 173 } 174 175 return ip, port, nil 176 }