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  }