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  }