github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/taskenv/services_test.go (about) 1 package taskenv 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/hashicorp/nomad/ci" 8 "github.com/hashicorp/nomad/helper/pointer" 9 "github.com/hashicorp/nomad/nomad/structs" 10 "github.com/stretchr/testify/require" 11 ) 12 13 // TestInterpolateServices asserts that all service 14 // and check fields are properly interpolated. 15 func TestInterpolateServices(t *testing.T) { 16 ci.Parallel(t) 17 18 services := []*structs.Service{ 19 { 20 Name: "${name}", 21 PortLabel: "${portlabel}", 22 Tags: []string{"${tags}"}, 23 Meta: map[string]string{ 24 "meta-key": "${meta}", 25 }, 26 CanaryMeta: map[string]string{ 27 "canarymeta-key": "${canarymeta}", 28 }, 29 Address: "${address}", 30 TaggedAddresses: map[string]string{ 31 "${ta-key}": "${ta-address}", 32 }, 33 Checks: []*structs.ServiceCheck{ 34 { 35 Name: "${checkname}", 36 Type: "${checktype}", 37 Command: "${checkcmd}", 38 Args: []string{"${checkarg}"}, 39 Path: "${checkstr}", 40 Protocol: "${checkproto}", 41 PortLabel: "${checklabel}", 42 InitialStatus: "${checkstatus}", 43 Method: "${checkmethod}", 44 Header: map[string][]string{ 45 "${checkheaderk}": {"${checkheaderv}"}, 46 }, 47 }, 48 }, 49 }, 50 } 51 52 env := &TaskEnv{ 53 EnvMap: map[string]string{ 54 "name": "name", 55 "portlabel": "portlabel", 56 "tags": "tags", 57 "meta": "meta-value", 58 "address": "example.com", 59 "ta-key": "public_wan", 60 "ta-address": "1.2.3.4", 61 "canarymeta": "canarymeta-value", 62 "checkname": "checkname", 63 "checktype": "checktype", 64 "checkcmd": "checkcmd", 65 "checkarg": "checkarg", 66 "checkstr": "checkstr", 67 "checkpath": "checkpath", 68 "checkproto": "checkproto", 69 "checklabel": "checklabel", 70 "checkstatus": "checkstatus", 71 "checkmethod": "checkmethod", 72 "checkheaderk": "checkheaderk", 73 "checkheaderv": "checkheaderv", 74 }, 75 } 76 77 interpolated := InterpolateServices(env, services) 78 79 exp := []*structs.Service{ 80 { 81 Name: "name", 82 PortLabel: "portlabel", 83 Tags: []string{"tags"}, 84 Meta: map[string]string{ 85 "meta-key": "meta-value", 86 }, 87 CanaryMeta: map[string]string{ 88 "canarymeta-key": "canarymeta-value", 89 }, 90 Address: "example.com", 91 TaggedAddresses: map[string]string{ 92 "public_wan": "1.2.3.4", 93 }, 94 Checks: []*structs.ServiceCheck{ 95 { 96 Name: "checkname", 97 Type: "checktype", 98 Command: "checkcmd", 99 Args: []string{"checkarg"}, 100 Path: "checkstr", 101 Protocol: "checkproto", 102 PortLabel: "checklabel", 103 InitialStatus: "checkstatus", 104 Method: "checkmethod", 105 Header: map[string][]string{ 106 "checkheaderk": {"checkheaderv"}, 107 }, 108 }, 109 }, 110 }, 111 } 112 113 require.Equal(t, exp, interpolated) 114 } 115 116 var testEnv = NewTaskEnv( 117 map[string]string{"foo": "bar", "baz": "blah"}, 118 map[string]string{"foo": "bar", "baz": "blah"}, 119 nil, nil, "", "") 120 121 func TestInterpolate_interpolateMapStringSliceString(t *testing.T) { 122 ci.Parallel(t) 123 124 t.Run("nil", func(t *testing.T) { 125 require.Nil(t, interpolateMapStringSliceString(testEnv, nil)) 126 }) 127 128 t.Run("not nil", func(t *testing.T) { 129 require.Equal(t, map[string][]string{ 130 "a": {"b"}, 131 "bar": {"blah", "c"}, 132 }, interpolateMapStringSliceString(testEnv, map[string][]string{ 133 "a": {"b"}, 134 "${foo}": {"${baz}", "c"}, 135 })) 136 }) 137 } 138 139 func TestInterpolate_interpolateMapStringString(t *testing.T) { 140 ci.Parallel(t) 141 142 t.Run("nil", func(t *testing.T) { 143 require.Nil(t, interpolateMapStringString(testEnv, nil)) 144 }) 145 146 t.Run("not nil", func(t *testing.T) { 147 require.Equal(t, map[string]string{ 148 "a": "b", 149 "bar": "blah", 150 }, interpolateMapStringString(testEnv, map[string]string{ 151 "a": "b", 152 "${foo}": "${baz}", 153 })) 154 }) 155 } 156 157 func TestInterpolate_interpolateMapStringInterface(t *testing.T) { 158 ci.Parallel(t) 159 160 t.Run("nil", func(t *testing.T) { 161 require.Nil(t, interpolateMapStringInterface(testEnv, nil)) 162 }) 163 164 t.Run("not nil", func(t *testing.T) { 165 require.Equal(t, map[string]interface{}{ 166 "a": 1, 167 "bar": 2, 168 }, interpolateMapStringInterface(testEnv, map[string]interface{}{ 169 "a": 1, 170 "${foo}": 2, 171 })) 172 }) 173 } 174 175 func TestInterpolate_interpolateConnect(t *testing.T) { 176 ci.Parallel(t) 177 178 e := map[string]string{ 179 "tag1": "_tag1", 180 "port1": "12345", 181 "address1": "1.2.3.4", 182 "destination1": "_dest1", 183 "datacenter1": "_datacenter1", 184 "localbindaddress1": "127.0.0.2", 185 "path1": "_path1", 186 "protocol1": "_protocol1", 187 "port2": "_port2", 188 "config1": "_config1", 189 "driver1": "_driver1", 190 "user1": "_user1", 191 "config2": "_config2", 192 "env1": "_env1", 193 "env2": "_env2", 194 "mode1": "_mode1", 195 "device1": "_device1", 196 "cidr1": "10.0.0.0/64", 197 "ip1": "1.1.1.1", 198 "server1": "10.0.0.1", 199 "search1": "10.0.0.2", 200 "option1": "10.0.0.3", 201 "port3": "_port3", 202 "network1": "_network1", 203 "port4": "_port4", 204 "network2": "_network2", 205 "resource1": "_resource1", 206 "meta1": "_meta1", 207 "meta2": "_meta2", 208 "signal1": "_signal1", 209 "bind1": "_bind1", 210 "address2": "10.0.0.4", 211 "config3": "_config3", 212 "protocol2": "_protocol2", 213 "service1": "_service1", 214 "host1": "_host1", 215 } 216 env := NewTaskEnv(e, e, nil, nil, "", "") 217 218 connect := &structs.ConsulConnect{ 219 Native: false, 220 SidecarService: &structs.ConsulSidecarService{ 221 Tags: []string{"${tag1}", "tag2"}, 222 Port: "${port1}", 223 Proxy: &structs.ConsulProxy{ 224 LocalServiceAddress: "${address1}", 225 LocalServicePort: 10000, 226 Upstreams: []structs.ConsulUpstream{{ 227 DestinationName: "${destination1}", 228 Datacenter: "${datacenter1}", 229 LocalBindPort: 10001, 230 LocalBindAddress: "${localbindaddress1}", 231 }}, 232 Expose: &structs.ConsulExposeConfig{ 233 Paths: []structs.ConsulExposePath{{ 234 Path: "${path1}", 235 Protocol: "${protocol1}", 236 ListenerPort: "${port2}", 237 LocalPathPort: 10002, 238 }}, 239 }, 240 Config: map[string]interface{}{ 241 "${config1}": 1, 242 "port": "${port1}", 243 }, 244 }, 245 }, 246 SidecarTask: &structs.SidecarTask{ 247 Name: "name", // not interpolated by taskenv 248 Driver: "${driver1}", 249 User: "${user1}", 250 Config: map[string]interface{}{"${config2}": 2}, 251 Env: map[string]string{"${env1}": "${env2}"}, 252 Resources: &structs.Resources{ 253 CPU: 1, 254 MemoryMB: 2, 255 DiskMB: 3, 256 IOPS: 4, 257 Networks: structs.Networks{{ 258 Mode: "${mode1}", 259 Device: "${device1}", 260 CIDR: "${cidr1}", 261 IP: "${ip1}", 262 MBits: 1, 263 DNS: &structs.DNSConfig{ 264 Servers: []string{"${server1}"}, 265 Searches: []string{"${search1}"}, 266 Options: []string{"${option1}"}, 267 }, 268 ReservedPorts: []structs.Port{{ 269 Label: "${port3}", 270 Value: 9000, 271 To: 9000, 272 HostNetwork: "${network1}", 273 }}, 274 DynamicPorts: []structs.Port{{ 275 Label: "${port4}", 276 Value: 9001, 277 To: 9001, 278 HostNetwork: "${network2}", 279 }}, 280 }}, 281 Devices: structs.ResourceDevices{{ 282 Name: "${resource1}", 283 }}, 284 }, 285 Meta: map[string]string{"${meta1}": "${meta2}"}, 286 KillTimeout: pointer.Of(1 * time.Second), 287 LogConfig: &structs.LogConfig{ 288 MaxFiles: 1, 289 MaxFileSizeMB: 2, 290 }, 291 ShutdownDelay: pointer.Of(2 * time.Second), 292 KillSignal: "${signal1}", 293 }, 294 Gateway: &structs.ConsulGateway{ 295 Proxy: &structs.ConsulGatewayProxy{ 296 ConnectTimeout: pointer.Of(3 * time.Second), 297 EnvoyGatewayBindTaggedAddresses: true, 298 EnvoyGatewayBindAddresses: map[string]*structs.ConsulGatewayBindAddress{ 299 "${bind1}": { 300 Address: "${address2}", 301 Port: 8000, 302 }, 303 }, 304 EnvoyGatewayNoDefaultBind: true, 305 Config: map[string]interface{}{ 306 "${config3}": 4, 307 }, 308 }, 309 Ingress: &structs.ConsulIngressConfigEntry{ 310 TLS: &structs.ConsulGatewayTLSConfig{ 311 Enabled: true, 312 }, 313 Listeners: []*structs.ConsulIngressListener{{ 314 Protocol: "${protocol2}", 315 Port: 8001, 316 Services: []*structs.ConsulIngressService{{ 317 Name: "${service1}", 318 Hosts: []string{"${host1}", "host2"}, 319 }}, 320 }}, 321 }, 322 }, 323 } 324 325 interpolateConnect(env, connect) 326 327 require.Equal(t, &structs.ConsulConnect{ 328 Native: false, 329 SidecarService: &structs.ConsulSidecarService{ 330 Tags: []string{"_tag1", "tag2"}, 331 Port: "12345", 332 Proxy: &structs.ConsulProxy{ 333 LocalServiceAddress: "1.2.3.4", 334 LocalServicePort: 10000, 335 Upstreams: []structs.ConsulUpstream{{ 336 DestinationName: "_dest1", 337 Datacenter: "_datacenter1", 338 LocalBindPort: 10001, 339 LocalBindAddress: "127.0.0.2", 340 }}, 341 Expose: &structs.ConsulExposeConfig{ 342 Paths: []structs.ConsulExposePath{{ 343 Path: "_path1", 344 Protocol: "_protocol1", 345 ListenerPort: "_port2", 346 LocalPathPort: 10002, 347 }}, 348 }, 349 Config: map[string]interface{}{ 350 "_config1": 1, 351 "port": "12345", 352 }, 353 }, 354 }, 355 SidecarTask: &structs.SidecarTask{ 356 Name: "name", // not interpolated by InterpolateServices 357 Driver: "_driver1", 358 User: "_user1", 359 Config: map[string]interface{}{"_config2": 2}, 360 Env: map[string]string{"_env1": "_env2"}, 361 Resources: &structs.Resources{ 362 CPU: 1, 363 MemoryMB: 2, 364 DiskMB: 3, 365 IOPS: 4, 366 Networks: structs.Networks{{ 367 Mode: "_mode1", 368 Device: "_device1", 369 CIDR: "10.0.0.0/64", 370 IP: "1.1.1.1", 371 MBits: 1, 372 DNS: &structs.DNSConfig{ 373 Servers: []string{"10.0.0.1"}, 374 Searches: []string{"10.0.0.2"}, 375 Options: []string{"10.0.0.3"}, 376 }, 377 ReservedPorts: []structs.Port{{ 378 Label: "_port3", 379 Value: 9000, 380 To: 9000, 381 HostNetwork: "_network1", 382 }}, 383 DynamicPorts: []structs.Port{{ 384 Label: "_port4", 385 Value: 9001, 386 To: 9001, 387 HostNetwork: "_network2", 388 }}, 389 }}, 390 Devices: structs.ResourceDevices{{ 391 Name: "_resource1", 392 }}, 393 }, 394 Meta: map[string]string{"_meta1": "_meta2"}, 395 KillTimeout: pointer.Of(1 * time.Second), 396 LogConfig: &structs.LogConfig{ 397 MaxFiles: 1, 398 MaxFileSizeMB: 2, 399 }, 400 ShutdownDelay: pointer.Of(2 * time.Second), 401 KillSignal: "_signal1", 402 }, 403 Gateway: &structs.ConsulGateway{ 404 Proxy: &structs.ConsulGatewayProxy{ 405 ConnectTimeout: pointer.Of(3 * time.Second), 406 EnvoyGatewayBindTaggedAddresses: true, 407 EnvoyGatewayBindAddresses: map[string]*structs.ConsulGatewayBindAddress{ 408 "_bind1": { 409 Address: "10.0.0.4", 410 Port: 8000, 411 }, 412 }, 413 EnvoyGatewayNoDefaultBind: true, 414 Config: map[string]interface{}{ 415 "_config3": 4, 416 }, 417 }, 418 Ingress: &structs.ConsulIngressConfigEntry{ 419 TLS: &structs.ConsulGatewayTLSConfig{ 420 Enabled: true, 421 }, 422 Listeners: []*structs.ConsulIngressListener{{ 423 Protocol: "_protocol2", 424 Port: 8001, 425 Services: []*structs.ConsulIngressService{{ 426 Name: "_service1", 427 Hosts: []string{"_host1", "host2"}, 428 }}, 429 }}, 430 }, 431 }, 432 }, connect) 433 }