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 }