github.com/outbrain/consul@v1.4.5/agent/structs/connect_proxy_config.go (about) 1 package structs 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/consul/api" 7 ) 8 9 // ConnectProxyConfig describes the configuration needed for any proxy managed 10 // or unmanaged. It describes a single logical service's listener and optionally 11 // upstreams and sidecar-related config for a single instance. To describe a 12 // centralized proxy that routed traffic for multiple services, a different one 13 // of these would be needed for each, sharing the same LogicalProxyID. 14 type ConnectProxyConfig struct { 15 // DestinationServiceName is required and is the name of the service to accept 16 // traffic for. 17 DestinationServiceName string `json:",omitempty"` 18 19 // DestinationServiceID is optional and should only be specified for 20 // "side-car" style proxies where the proxy is in front of just a single 21 // instance of the service. It should be set to the service ID of the instance 22 // being represented which must be registered to the same agent. It's valid to 23 // provide a service ID that does not yet exist to avoid timing issues when 24 // bootstrapping a service with a proxy. 25 DestinationServiceID string `json:",omitempty"` 26 27 // LocalServiceAddress is the address of the local service instance. It is 28 // optional and should only be specified for "side-car" style proxies. It will 29 // default to 127.0.0.1 if the proxy is a "side-car" (DestinationServiceID is 30 // set) but otherwise will be ignored. 31 LocalServiceAddress string `json:",omitempty"` 32 33 // LocalServicePort is the port of the local service instance. It is optional 34 // and should only be specified for "side-car" style proxies. It will default 35 // to the registered port for the instance if the proxy is a "side-car" 36 // (DestinationServiceID is set) but otherwise will be ignored. 37 LocalServicePort int `json:",omitempty"` 38 39 // Config is the arbitrary configuration data provided with the proxy 40 // registration. 41 Config map[string]interface{} `json:",omitempty"` 42 43 // Upstreams describes any upstream dependencies the proxy instance should 44 // setup. 45 Upstreams Upstreams `json:",omitempty"` 46 } 47 48 // ToAPI returns the api struct with the same fields. We have duplicates to 49 // avoid the api package depending on this one which imports a ton of Consul's 50 // core which you don't want if you are just trying to use our client in your 51 // app. 52 func (c *ConnectProxyConfig) ToAPI() *api.AgentServiceConnectProxyConfig { 53 return &api.AgentServiceConnectProxyConfig{ 54 DestinationServiceName: c.DestinationServiceName, 55 DestinationServiceID: c.DestinationServiceID, 56 LocalServiceAddress: c.LocalServiceAddress, 57 LocalServicePort: c.LocalServicePort, 58 Config: c.Config, 59 Upstreams: c.Upstreams.ToAPI(), 60 } 61 } 62 63 const ( 64 UpstreamDestTypeService = "service" 65 UpstreamDestTypePreparedQuery = "prepared_query" 66 ) 67 68 // Upstreams is a list of upstreams. Aliased to allow ToAPI method. 69 type Upstreams []Upstream 70 71 // ToAPI returns the api structs with the same fields. We have duplicates to 72 // avoid the api package depending on this one which imports a ton of Consul's 73 // core which you don't want if you are just trying to use our client in your 74 // app. 75 func (us Upstreams) ToAPI() []api.Upstream { 76 a := make([]api.Upstream, len(us)) 77 for i, u := range us { 78 a[i] = u.ToAPI() 79 } 80 return a 81 } 82 83 // UpstreamsFromAPI is a helper for converting api.Upstream to Upstream. 84 func UpstreamsFromAPI(us []api.Upstream) Upstreams { 85 a := make([]Upstream, len(us)) 86 for i, u := range us { 87 a[i] = UpstreamFromAPI(u) 88 } 89 return a 90 } 91 92 // Upstream represents a single upstream dependency for a service or proxy. It 93 // describes the mechanism used to discover instances to communicate with (the 94 // Target) as well as any potential client configuration that may be useful such 95 // as load balancer options, timeouts etc. 96 type Upstream struct { 97 // Destination fields are the required ones for determining what this upstream 98 // points to. Depending on DestinationType some other fields below might 99 // further restrict the set of instances allowable. 100 // 101 // DestinationType would be better as an int constant but even with custom 102 // JSON marshallers it causes havoc with all the mapstructure mangling we do 103 // on service definitions in various places. 104 DestinationType string 105 DestinationNamespace string `json:",omitempty"` 106 DestinationName string 107 108 // Datacenter that the service discovery request should be run against. Note 109 // for prepared queries, the actual results might be from a different 110 // datacenter. 111 Datacenter string 112 113 // LocalBindAddress is the ip address a side-car proxy should listen on for 114 // traffic destined for this upstream service. Default if empty is 127.0.0.1. 115 LocalBindAddress string `json:",omitempty"` 116 117 // LocalBindPort is the ip address a side-car proxy should listen on for traffic 118 // destined for this upstream service. Required. 119 LocalBindPort int 120 121 // Config is an opaque config that is specific to the proxy process being run. 122 // It can be used to pass arbitrary configuration for this specific upstream 123 // to the proxy. 124 Config map[string]interface{} 125 } 126 127 // Validate sanity checks the struct is valid 128 func (u *Upstream) Validate() error { 129 if u.DestinationType != UpstreamDestTypeService && 130 u.DestinationType != UpstreamDestTypePreparedQuery { 131 return fmt.Errorf("unknown upstream destination type") 132 } 133 134 if u.DestinationName == "" { 135 return fmt.Errorf("upstream destination name cannot be empty") 136 } 137 138 if u.LocalBindPort == 0 { 139 return fmt.Errorf("upstream local bind port cannot be zero") 140 } 141 return nil 142 } 143 144 // ToAPI returns the api structs with the same fields. We have duplicates to 145 // avoid the api package depending on this one which imports a ton of Consul's 146 // core which you don't want if you are just trying to use our client in your 147 // app. 148 func (u *Upstream) ToAPI() api.Upstream { 149 return api.Upstream{ 150 DestinationType: api.UpstreamDestType(u.DestinationType), 151 DestinationNamespace: u.DestinationNamespace, 152 DestinationName: u.DestinationName, 153 Datacenter: u.Datacenter, 154 LocalBindAddress: u.LocalBindAddress, 155 LocalBindPort: u.LocalBindPort, 156 Config: u.Config, 157 } 158 } 159 160 // Identifier returns a string representation that uniquely identifies the 161 // upstream in a canonical but human readable way. 162 func (u *Upstream) Identifier() string { 163 name := u.DestinationName 164 if u.DestinationNamespace != "" && u.DestinationNamespace != "default" { 165 name = u.DestinationNamespace + "/" + u.DestinationName 166 } 167 if u.Datacenter != "" { 168 name += "?dc=" + u.Datacenter 169 } 170 typ := u.DestinationType 171 if typ == "" { 172 typ = UpstreamDestTypeService 173 } 174 return typ + ":" + name 175 } 176 177 // String implements Stringer by returning the Identifier. 178 func (u *Upstream) String() string { 179 return u.Identifier() 180 } 181 182 // UpstreamFromAPI is a helper for converting api.Upstream to Upstream. 183 func UpstreamFromAPI(u api.Upstream) Upstream { 184 return Upstream{ 185 DestinationType: string(u.DestinationType), 186 DestinationNamespace: u.DestinationNamespace, 187 DestinationName: u.DestinationName, 188 Datacenter: u.Datacenter, 189 LocalBindAddress: u.LocalBindAddress, 190 LocalBindPort: u.LocalBindPort, 191 Config: u.Config, 192 } 193 }