github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/taskenv/services.go (about)

     1  package taskenv
     2  
     3  import (
     4  	"github.com/hashicorp/nomad/nomad/structs"
     5  )
     6  
     7  // InterpolateServices returns an interpolated copy of services and checks with
     8  // values from the task's environment.
     9  func InterpolateServices(taskEnv *TaskEnv, services []*structs.Service) []*structs.Service {
    10  	// Guard against not having a valid taskEnv. This can be the case if the
    11  	// PreKilling or Exited hook is run before Poststart.
    12  	if taskEnv == nil || len(services) == 0 {
    13  		return nil
    14  	}
    15  
    16  	interpolated := make([]*structs.Service, len(services))
    17  
    18  	for i, origService := range services {
    19  		// Create a copy as we need to re-interpolate every time the
    20  		// environment changes.
    21  		service := origService.Copy()
    22  
    23  		for _, check := range service.Checks {
    24  			check.Name = taskEnv.ReplaceEnv(check.Name)
    25  			check.Type = taskEnv.ReplaceEnv(check.Type)
    26  			check.Command = taskEnv.ReplaceEnv(check.Command)
    27  			check.Args = taskEnv.ParseAndReplace(check.Args)
    28  			check.Path = taskEnv.ReplaceEnv(check.Path)
    29  			check.Protocol = taskEnv.ReplaceEnv(check.Protocol)
    30  			check.PortLabel = taskEnv.ReplaceEnv(check.PortLabel)
    31  			check.InitialStatus = taskEnv.ReplaceEnv(check.InitialStatus)
    32  			check.Method = taskEnv.ReplaceEnv(check.Method)
    33  			check.GRPCService = taskEnv.ReplaceEnv(check.GRPCService)
    34  			check.Header = interpolateMapStringSliceString(taskEnv, check.Header)
    35  		}
    36  
    37  		service.Name = taskEnv.ReplaceEnv(service.Name)
    38  		service.PortLabel = taskEnv.ReplaceEnv(service.PortLabel)
    39  		service.Address = taskEnv.ReplaceEnv(service.Address)
    40  		service.Tags = taskEnv.ParseAndReplace(service.Tags)
    41  		service.CanaryTags = taskEnv.ParseAndReplace(service.CanaryTags)
    42  		service.Meta = interpolateMapStringString(taskEnv, service.Meta)
    43  		service.CanaryMeta = interpolateMapStringString(taskEnv, service.CanaryMeta)
    44  		service.TaggedAddresses = interpolateMapStringString(taskEnv, service.TaggedAddresses)
    45  		interpolateConnect(taskEnv, service.Connect)
    46  
    47  		interpolated[i] = service
    48  	}
    49  
    50  	return interpolated
    51  }
    52  
    53  func interpolateMapStringSliceString(taskEnv *TaskEnv, orig map[string][]string) map[string][]string {
    54  	if len(orig) == 0 {
    55  		return nil
    56  	}
    57  
    58  	m := make(map[string][]string, len(orig))
    59  	for k, vs := range orig {
    60  		m[taskEnv.ReplaceEnv(k)] = taskEnv.ParseAndReplace(vs)
    61  	}
    62  	return m
    63  }
    64  
    65  func interpolateMapStringString(taskEnv *TaskEnv, orig map[string]string) map[string]string {
    66  	if len(orig) == 0 {
    67  		return nil
    68  	}
    69  
    70  	m := make(map[string]string, len(orig))
    71  	for k, v := range orig {
    72  		m[taskEnv.ReplaceEnv(k)] = taskEnv.ReplaceEnv(v)
    73  	}
    74  	return m
    75  }
    76  
    77  func interpolateMapStringInterface(taskEnv *TaskEnv, orig map[string]interface{}) map[string]interface{} {
    78  	if len(orig) == 0 {
    79  		return nil
    80  	}
    81  
    82  	m := make(map[string]interface{}, len(orig))
    83  	for k, v := range orig {
    84  		envK := taskEnv.ReplaceEnv(k)
    85  		if vStr, ok := v.(string); ok {
    86  			m[envK] = taskEnv.ReplaceEnv(vStr)
    87  		} else {
    88  			m[envK] = v
    89  		}
    90  	}
    91  	return m
    92  }
    93  
    94  func interpolateConnect(taskEnv *TaskEnv, connect *structs.ConsulConnect) {
    95  	if connect == nil {
    96  		return
    97  	}
    98  
    99  	interpolateConnectSidecarService(taskEnv, connect.SidecarService)
   100  	interpolateConnectSidecarTask(taskEnv, connect.SidecarTask)
   101  	if connect.Gateway != nil {
   102  		interpolateConnectGatewayProxy(taskEnv, connect.Gateway.Proxy)
   103  		interpolateConnectGatewayIngress(taskEnv, connect.Gateway.Ingress)
   104  	}
   105  }
   106  
   107  func interpolateConnectGatewayProxy(taskEnv *TaskEnv, proxy *structs.ConsulGatewayProxy) {
   108  	if proxy == nil {
   109  		return
   110  	}
   111  
   112  	m := make(map[string]*structs.ConsulGatewayBindAddress, len(proxy.EnvoyGatewayBindAddresses))
   113  	for k, v := range proxy.EnvoyGatewayBindAddresses {
   114  		m[taskEnv.ReplaceEnv(k)] = &structs.ConsulGatewayBindAddress{
   115  			Address: taskEnv.ReplaceEnv(v.Address),
   116  			Port:    v.Port,
   117  		}
   118  	}
   119  
   120  	proxy.EnvoyGatewayBindAddresses = m
   121  	proxy.Config = interpolateMapStringInterface(taskEnv, proxy.Config)
   122  }
   123  
   124  func interpolateConnectGatewayIngress(taskEnv *TaskEnv, ingress *structs.ConsulIngressConfigEntry) {
   125  	if ingress == nil {
   126  		return
   127  	}
   128  
   129  	for _, listener := range ingress.Listeners {
   130  		listener.Protocol = taskEnv.ReplaceEnv(listener.Protocol)
   131  		for _, service := range listener.Services {
   132  			service.Name = taskEnv.ReplaceEnv(service.Name)
   133  			service.Hosts = taskEnv.ParseAndReplace(service.Hosts)
   134  		}
   135  	}
   136  }
   137  
   138  func interpolateConnectSidecarService(taskEnv *TaskEnv, sidecar *structs.ConsulSidecarService) {
   139  	if sidecar == nil {
   140  		return
   141  	}
   142  
   143  	sidecar.Port = taskEnv.ReplaceEnv(sidecar.Port)
   144  	sidecar.Tags = taskEnv.ParseAndReplace(sidecar.Tags)
   145  	if sidecar.Proxy != nil {
   146  		sidecar.Proxy.LocalServiceAddress = taskEnv.ReplaceEnv(sidecar.Proxy.LocalServiceAddress)
   147  		if sidecar.Proxy.Expose != nil {
   148  			for i := 0; i < len(sidecar.Proxy.Expose.Paths); i++ {
   149  				sidecar.Proxy.Expose.Paths[i].Protocol = taskEnv.ReplaceEnv(sidecar.Proxy.Expose.Paths[i].Protocol)
   150  				sidecar.Proxy.Expose.Paths[i].ListenerPort = taskEnv.ReplaceEnv(sidecar.Proxy.Expose.Paths[i].ListenerPort)
   151  				sidecar.Proxy.Expose.Paths[i].Path = taskEnv.ReplaceEnv(sidecar.Proxy.Expose.Paths[i].Path)
   152  			}
   153  		}
   154  		for i := 0; i < len(sidecar.Proxy.Upstreams); i++ {
   155  			sidecar.Proxy.Upstreams[i].Datacenter = taskEnv.ReplaceEnv(sidecar.Proxy.Upstreams[i].Datacenter)
   156  			sidecar.Proxy.Upstreams[i].DestinationName = taskEnv.ReplaceEnv(sidecar.Proxy.Upstreams[i].DestinationName)
   157  			sidecar.Proxy.Upstreams[i].LocalBindAddress = taskEnv.ReplaceEnv(sidecar.Proxy.Upstreams[i].LocalBindAddress)
   158  		}
   159  		sidecar.Proxy.Config = interpolateMapStringInterface(taskEnv, sidecar.Proxy.Config)
   160  	}
   161  }
   162  
   163  func interpolateConnectSidecarTask(taskEnv *TaskEnv, task *structs.SidecarTask) {
   164  	if task == nil {
   165  		return
   166  	}
   167  
   168  	task.Driver = taskEnv.ReplaceEnv(task.Driver)
   169  	task.Config = interpolateMapStringInterface(taskEnv, task.Config)
   170  	task.Env = interpolateMapStringString(taskEnv, task.Env)
   171  	task.KillSignal = taskEnv.ReplaceEnv(task.KillSignal)
   172  	task.Meta = interpolateMapStringString(taskEnv, task.Meta)
   173  	interpolateTaskResources(taskEnv, task.Resources)
   174  	task.User = taskEnv.ReplaceEnv(task.User)
   175  }
   176  
   177  func interpolateTaskResources(taskEnv *TaskEnv, resources *structs.Resources) {
   178  	if resources == nil {
   179  		return
   180  	}
   181  
   182  	for i := 0; i < len(resources.Devices); i++ {
   183  		resources.Devices[i].Name = taskEnv.ReplaceEnv(resources.Devices[i].Name)
   184  		// do not interpolate constraints & affinities
   185  	}
   186  
   187  	for i := 0; i < len(resources.Networks); i++ {
   188  		resources.Networks[i].CIDR = taskEnv.ReplaceEnv(resources.Networks[i].CIDR)
   189  		resources.Networks[i].Device = taskEnv.ReplaceEnv(resources.Networks[i].Device)
   190  		resources.Networks[i].IP = taskEnv.ReplaceEnv(resources.Networks[i].IP)
   191  		resources.Networks[i].Mode = taskEnv.ReplaceEnv(resources.Networks[i].Mode)
   192  
   193  		if resources.Networks[i].DNS != nil {
   194  			resources.Networks[i].DNS.Options = taskEnv.ParseAndReplace(resources.Networks[i].DNS.Options)
   195  			resources.Networks[i].DNS.Searches = taskEnv.ParseAndReplace(resources.Networks[i].DNS.Searches)
   196  			resources.Networks[i].DNS.Servers = taskEnv.ParseAndReplace(resources.Networks[i].DNS.Servers)
   197  		}
   198  
   199  		for p := 0; p < len(resources.Networks[i].DynamicPorts); p++ {
   200  			resources.Networks[i].DynamicPorts[p].HostNetwork = taskEnv.ReplaceEnv(resources.Networks[i].DynamicPorts[p].HostNetwork)
   201  			resources.Networks[i].DynamicPorts[p].Label = taskEnv.ReplaceEnv(resources.Networks[i].DynamicPorts[p].Label)
   202  		}
   203  
   204  		for p := 0; p < len(resources.Networks[i].ReservedPorts); p++ {
   205  			resources.Networks[i].ReservedPorts[p].HostNetwork = taskEnv.ReplaceEnv(resources.Networks[i].ReservedPorts[p].HostNetwork)
   206  			resources.Networks[i].ReservedPorts[p].Label = taskEnv.ReplaceEnv(resources.Networks[i].ReservedPorts[p].Label)
   207  		}
   208  	}
   209  }