2019-08-15 15:22:37 +00:00
|
|
|
package nomad
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"testing"
|
2020-07-28 20:12:08 +00:00
|
|
|
"time"
|
2019-08-15 15:22:37 +00:00
|
|
|
|
2020-07-28 20:12:08 +00:00
|
|
|
"github.com/hashicorp/nomad/helper"
|
2019-12-12 23:46:14 +00:00
|
|
|
"github.com/hashicorp/nomad/helper/testlog"
|
|
|
|
"github.com/hashicorp/nomad/nomad/mock"
|
2019-08-15 15:22:37 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
2020-06-22 17:55:59 +00:00
|
|
|
func TestJobEndpointConnect_isSidecarForService(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2019-08-15 15:22:37 +00:00
|
|
|
cases := []struct {
|
|
|
|
t *structs.Task // task
|
|
|
|
s string // service
|
|
|
|
r bool // result
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
&structs.Task{},
|
|
|
|
"api",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&structs.Task{
|
|
|
|
Kind: "connect-proxy:api",
|
|
|
|
},
|
|
|
|
"api",
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&structs.Task{
|
|
|
|
Kind: "connect-proxy:api",
|
|
|
|
},
|
|
|
|
"db",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&structs.Task{
|
|
|
|
Kind: "api",
|
|
|
|
},
|
|
|
|
"api",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, c := range cases {
|
|
|
|
require.Equal(t, c.r, isSidecarForService(c.t, c.s))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-22 17:55:59 +00:00
|
|
|
func TestJobEndpointConnect_groupConnectHook(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2019-08-15 15:22:37 +00:00
|
|
|
// Test that connect-proxy task is inserted for backend service
|
2019-12-12 23:46:14 +00:00
|
|
|
job := mock.Job()
|
2020-11-16 16:41:19 +00:00
|
|
|
|
|
|
|
job.Meta = map[string]string{
|
|
|
|
"backend_name": "backend",
|
|
|
|
"admin_name": "admin",
|
|
|
|
}
|
|
|
|
|
2019-12-12 23:46:14 +00:00
|
|
|
job.TaskGroups[0] = &structs.TaskGroup{
|
2020-11-16 16:41:19 +00:00
|
|
|
Networks: structs.Networks{{
|
|
|
|
Mode: "bridge",
|
|
|
|
}},
|
|
|
|
Services: []*structs.Service{{
|
|
|
|
Name: "${NOMAD_META_backend_name}",
|
|
|
|
PortLabel: "8080",
|
|
|
|
Connect: &structs.ConsulConnect{
|
|
|
|
SidecarService: &structs.ConsulSidecarService{},
|
2019-08-15 15:22:37 +00:00
|
|
|
},
|
2020-11-16 16:41:19 +00:00
|
|
|
}, {
|
|
|
|
Name: "${NOMAD_META_admin_name}",
|
|
|
|
PortLabel: "9090",
|
|
|
|
Connect: &structs.ConsulConnect{
|
|
|
|
SidecarService: &structs.ConsulSidecarService{},
|
2019-08-15 15:22:37 +00:00
|
|
|
},
|
2020-11-16 16:41:19 +00:00
|
|
|
}},
|
2019-08-15 15:22:37 +00:00
|
|
|
}
|
|
|
|
|
2019-12-12 23:46:14 +00:00
|
|
|
// Expected tasks
|
2020-11-16 16:41:19 +00:00
|
|
|
tgExp := job.TaskGroups[0].Copy()
|
|
|
|
tgExp.Tasks = []*structs.Task{
|
2020-12-15 20:38:33 +00:00
|
|
|
newConnectSidecarTask("backend"),
|
|
|
|
newConnectSidecarTask("admin"),
|
2019-08-15 15:22:37 +00:00
|
|
|
}
|
2020-11-16 16:41:19 +00:00
|
|
|
tgExp.Services[0].Name = "backend"
|
|
|
|
tgExp.Services[1].Name = "admin"
|
2019-12-12 23:46:14 +00:00
|
|
|
|
2020-12-14 22:41:14 +00:00
|
|
|
// Expect sidecar tasks to be in canonical form.
|
2020-11-16 16:41:19 +00:00
|
|
|
tgExp.Tasks[0].Canonicalize(job, tgExp)
|
|
|
|
tgExp.Tasks[1].Canonicalize(job, tgExp)
|
|
|
|
tgExp.Networks[0].DynamicPorts = []structs.Port{{
|
|
|
|
Label: fmt.Sprintf("%s-%s", structs.ConnectProxyPrefix, "backend"),
|
|
|
|
To: -1,
|
|
|
|
}, {
|
|
|
|
Label: fmt.Sprintf("%s-%s", structs.ConnectProxyPrefix, "admin"),
|
|
|
|
To: -1,
|
|
|
|
}}
|
|
|
|
tgExp.Networks[0].Canonicalize()
|
2019-08-15 15:22:37 +00:00
|
|
|
|
2019-12-12 23:46:14 +00:00
|
|
|
require.NoError(t, groupConnectHook(job, job.TaskGroups[0]))
|
2020-11-16 16:41:19 +00:00
|
|
|
require.Exactly(t, tgExp, job.TaskGroups[0])
|
2019-08-15 15:22:37 +00:00
|
|
|
|
|
|
|
// Test that hook is idempotent
|
2019-12-12 23:46:14 +00:00
|
|
|
require.NoError(t, groupConnectHook(job, job.TaskGroups[0]))
|
2020-11-16 16:41:19 +00:00
|
|
|
require.Exactly(t, tgExp, job.TaskGroups[0])
|
2019-12-12 23:46:14 +00:00
|
|
|
}
|
|
|
|
|
2020-07-28 20:12:08 +00:00
|
|
|
func TestJobEndpointConnect_groupConnectHook_IngressGateway(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
// Test that the connect gateway task is inserted if a gateway service exists
|
|
|
|
// and since this is a bridge network, will rewrite the default gateway proxy
|
|
|
|
// block with correct configuration.
|
|
|
|
job := mock.ConnectIngressGatewayJob("bridge", false)
|
|
|
|
|
2020-11-16 16:41:19 +00:00
|
|
|
job.Meta = map[string]string{
|
|
|
|
"gateway_name": "my-gateway",
|
|
|
|
}
|
|
|
|
|
|
|
|
job.TaskGroups[0].Services[0].Name = "${NOMAD_META_gateway_name}"
|
|
|
|
|
2020-07-28 20:12:08 +00:00
|
|
|
expTG := job.TaskGroups[0].Copy()
|
|
|
|
expTG.Tasks = []*structs.Task{
|
|
|
|
// inject the gateway task
|
2020-12-15 20:38:33 +00:00
|
|
|
newConnectGatewayTask(structs.ConnectIngressPrefix, "my-gateway", false),
|
2020-07-28 20:12:08 +00:00
|
|
|
}
|
2020-11-16 16:41:19 +00:00
|
|
|
expTG.Services[0].Name = "my-gateway"
|
2020-07-28 20:12:08 +00:00
|
|
|
expTG.Tasks[0].Canonicalize(job, expTG)
|
|
|
|
expTG.Networks[0].Canonicalize()
|
|
|
|
|
|
|
|
// rewrite the service gateway proxy configuration
|
|
|
|
expTG.Services[0].Connect.Gateway.Proxy = gatewayProxyForBridge(expTG.Services[0].Connect.Gateway)
|
|
|
|
|
|
|
|
require.NoError(t, groupConnectHook(job, job.TaskGroups[0]))
|
|
|
|
require.Exactly(t, expTG, job.TaskGroups[0])
|
|
|
|
|
|
|
|
// Test that the hook is idempotent
|
|
|
|
require.NoError(t, groupConnectHook(job, job.TaskGroups[0]))
|
|
|
|
require.Exactly(t, expTG, job.TaskGroups[0])
|
|
|
|
}
|
|
|
|
|
2020-12-14 22:41:14 +00:00
|
|
|
func TestJobEndpointConnect_groupConnectHook_IngressGateway_CustomTask(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
// Test that the connect gateway task is inserted if a gateway service exists
|
|
|
|
// and since this is a bridge network, will rewrite the default gateway proxy
|
|
|
|
// block with correct configuration.
|
|
|
|
job := mock.ConnectIngressGatewayJob("bridge", false)
|
|
|
|
|
|
|
|
job.Meta = map[string]string{
|
|
|
|
"gateway_name": "my-gateway",
|
|
|
|
}
|
|
|
|
|
|
|
|
job.TaskGroups[0].Services[0].Name = "${NOMAD_META_gateway_name}"
|
|
|
|
job.TaskGroups[0].Services[0].Connect.SidecarTask = &structs.SidecarTask{
|
|
|
|
Driver: "raw_exec",
|
|
|
|
User: "sidecars",
|
|
|
|
Config: map[string]interface{}{
|
|
|
|
"command": "/bin/sidecar",
|
|
|
|
"args": []string{"a", "b"},
|
|
|
|
},
|
|
|
|
Resources: &structs.Resources{
|
|
|
|
CPU: 400,
|
|
|
|
// Memory: inherit 128
|
|
|
|
},
|
|
|
|
KillSignal: "SIGHUP",
|
|
|
|
}
|
|
|
|
|
|
|
|
expTG := job.TaskGroups[0].Copy()
|
|
|
|
expTG.Tasks = []*structs.Task{
|
|
|
|
// inject merged gateway task
|
|
|
|
{
|
|
|
|
Name: "connect-ingress-my-gateway",
|
|
|
|
Kind: structs.NewTaskKind(structs.ConnectIngressPrefix, "my-gateway"),
|
|
|
|
Driver: "raw_exec",
|
|
|
|
User: "sidecars",
|
|
|
|
Config: map[string]interface{}{
|
|
|
|
"command": "/bin/sidecar",
|
|
|
|
"args": []string{"a", "b"},
|
|
|
|
},
|
|
|
|
Resources: &structs.Resources{
|
|
|
|
CPU: 400,
|
|
|
|
MemoryMB: 128,
|
|
|
|
},
|
|
|
|
LogConfig: &structs.LogConfig{
|
|
|
|
MaxFiles: 2,
|
|
|
|
MaxFileSizeMB: 2,
|
|
|
|
},
|
|
|
|
ShutdownDelay: 5 * time.Second,
|
|
|
|
KillSignal: "SIGHUP",
|
|
|
|
Constraints: structs.Constraints{
|
|
|
|
connectGatewayVersionConstraint(),
|
2021-06-03 18:47:39 +00:00
|
|
|
connectEnabledConstraint(),
|
|
|
|
connectListenerConstraint(),
|
2020-12-14 22:41:14 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
expTG.Services[0].Name = "my-gateway"
|
|
|
|
expTG.Tasks[0].Canonicalize(job, expTG)
|
|
|
|
expTG.Networks[0].Canonicalize()
|
|
|
|
|
|
|
|
// rewrite the service gateway proxy configuration
|
|
|
|
expTG.Services[0].Connect.Gateway.Proxy = gatewayProxyForBridge(expTG.Services[0].Connect.Gateway)
|
|
|
|
|
|
|
|
require.NoError(t, groupConnectHook(job, job.TaskGroups[0]))
|
|
|
|
require.Exactly(t, expTG, job.TaskGroups[0])
|
|
|
|
|
|
|
|
// Test that the hook is idempotent
|
|
|
|
require.NoError(t, groupConnectHook(job, job.TaskGroups[0]))
|
|
|
|
require.Exactly(t, expTG, job.TaskGroups[0])
|
|
|
|
}
|
|
|
|
|
2019-12-12 23:46:14 +00:00
|
|
|
// TestJobEndpoint_ConnectInterpolation asserts that when a Connect sidecar
|
|
|
|
// proxy task is being created for a group service with an interpolated name,
|
|
|
|
// the service name is interpolated *before the task is created.
|
|
|
|
//
|
|
|
|
// See https://github.com/hashicorp/nomad/issues/6853
|
2020-06-22 17:55:59 +00:00
|
|
|
func TestJobEndpointConnect_ConnectInterpolation(t *testing.T) {
|
2019-12-12 23:46:14 +00:00
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
server := &Server{logger: testlog.HCLogger(t)}
|
|
|
|
jobEndpoint := NewJobEndpoints(server)
|
|
|
|
|
|
|
|
j := mock.ConnectJob()
|
|
|
|
j.TaskGroups[0].Services[0].Name = "${JOB}-api"
|
|
|
|
j, warnings, err := jobEndpoint.admissionMutators(j)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Nil(t, warnings)
|
|
|
|
|
|
|
|
require.Len(t, j.TaskGroups[0].Tasks, 2)
|
|
|
|
require.Equal(t, "connect-proxy-my-job-api", j.TaskGroups[0].Tasks[1].Name)
|
2019-08-15 15:22:37 +00:00
|
|
|
}
|
2020-06-22 17:55:59 +00:00
|
|
|
|
|
|
|
func TestJobEndpointConnect_groupConnectSidecarValidate(t *testing.T) {
|
2020-07-28 20:12:08 +00:00
|
|
|
t.Parallel()
|
|
|
|
|
2021-04-27 16:23:57 +00:00
|
|
|
// network validation
|
|
|
|
|
|
|
|
makeService := func(name string) *structs.Service {
|
|
|
|
return &structs.Service{Name: name, Connect: &structs.ConsulConnect{
|
|
|
|
SidecarService: new(structs.ConsulSidecarService),
|
|
|
|
}}
|
|
|
|
}
|
|
|
|
|
2020-06-22 17:55:59 +00:00
|
|
|
t.Run("sidecar 0 networks", func(t *testing.T) {
|
|
|
|
require.EqualError(t, groupConnectSidecarValidate(&structs.TaskGroup{
|
|
|
|
Name: "g1",
|
|
|
|
Networks: nil,
|
2021-04-27 16:23:57 +00:00
|
|
|
}, makeService("connect-service")), `Consul Connect sidecars require exactly 1 network, found 0 in group "g1"`)
|
2020-06-22 17:55:59 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("sidecar non bridge", func(t *testing.T) {
|
|
|
|
require.EqualError(t, groupConnectSidecarValidate(&structs.TaskGroup{
|
|
|
|
Name: "g2",
|
|
|
|
Networks: structs.Networks{{
|
|
|
|
Mode: "host",
|
|
|
|
}},
|
2021-04-27 16:23:57 +00:00
|
|
|
}, makeService("connect-service")), `Consul Connect sidecar requires bridge network, found "host" in group "g2"`)
|
2020-06-22 17:55:59 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("sidecar okay", func(t *testing.T) {
|
|
|
|
require.NoError(t, groupConnectSidecarValidate(&structs.TaskGroup{
|
|
|
|
Name: "g3",
|
|
|
|
Networks: structs.Networks{{
|
|
|
|
Mode: "bridge",
|
|
|
|
}},
|
2021-04-27 16:23:57 +00:00
|
|
|
}, makeService("connect-service")))
|
|
|
|
})
|
|
|
|
|
|
|
|
// group and service name validation
|
|
|
|
|
|
|
|
t.Run("non-connect service contains uppercase characters", func(t *testing.T) {
|
|
|
|
_, err := groupConnectValidate(&structs.TaskGroup{
|
|
|
|
Name: "group",
|
|
|
|
Networks: structs.Networks{{Mode: "bridge"}},
|
|
|
|
Services: []*structs.Service{{
|
|
|
|
Name: "Other-Service",
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("connect service contains uppercase characters", func(t *testing.T) {
|
|
|
|
_, err := groupConnectValidate(&structs.TaskGroup{
|
|
|
|
Name: "group",
|
|
|
|
Networks: structs.Networks{{Mode: "bridge"}},
|
|
|
|
Services: []*structs.Service{{
|
|
|
|
Name: "Other-Service",
|
|
|
|
}, makeService("Connect-Service")},
|
|
|
|
})
|
|
|
|
require.EqualError(t, err, `Consul Connect service name "Connect-Service" in group "group" must not contain uppercase characters`)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("non-connect group contains uppercase characters", func(t *testing.T) {
|
|
|
|
_, err := groupConnectValidate(&structs.TaskGroup{
|
|
|
|
Name: "Other-Group",
|
|
|
|
Networks: structs.Networks{{Mode: "bridge"}},
|
|
|
|
Services: []*structs.Service{{
|
|
|
|
Name: "other-service",
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("connect-group contains uppercase characters", func(t *testing.T) {
|
|
|
|
_, err := groupConnectValidate(&structs.TaskGroup{
|
|
|
|
Name: "Connect-Group",
|
|
|
|
Networks: structs.Networks{{Mode: "bridge"}},
|
|
|
|
Services: []*structs.Service{{
|
|
|
|
Name: "other-service",
|
|
|
|
}, makeService("connect-service")},
|
|
|
|
})
|
|
|
|
require.EqualError(t, err, `Consul Connect group "Connect-Group" with service "connect-service" must not contain uppercase characters`)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("connect group and service lowercase", func(t *testing.T) {
|
|
|
|
_, err := groupConnectValidate(&structs.TaskGroup{
|
|
|
|
Name: "connect-group",
|
|
|
|
Networks: structs.Networks{{Mode: "bridge"}},
|
|
|
|
Services: []*structs.Service{{
|
|
|
|
Name: "other-service",
|
|
|
|
}, makeService("connect-service")},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
2020-06-22 17:55:59 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-07-08 15:19:36 +00:00
|
|
|
func TestJobEndpointConnect_getNamedTaskForNativeService(t *testing.T) {
|
2020-07-28 20:12:08 +00:00
|
|
|
t.Parallel()
|
|
|
|
|
2020-07-08 15:19:36 +00:00
|
|
|
t.Run("named exists", func(t *testing.T) {
|
|
|
|
task, err := getNamedTaskForNativeService(&structs.TaskGroup{
|
|
|
|
Name: "g1",
|
|
|
|
Tasks: []*structs.Task{{Name: "t1"}, {Name: "t2"}},
|
|
|
|
}, "s1", "t2")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "t2", task.Name)
|
2020-06-22 17:55:59 +00:00
|
|
|
})
|
|
|
|
|
2020-07-08 15:19:36 +00:00
|
|
|
t.Run("infer exists", func(t *testing.T) {
|
|
|
|
task, err := getNamedTaskForNativeService(&structs.TaskGroup{
|
|
|
|
Name: "g1",
|
|
|
|
Tasks: []*structs.Task{{Name: "t2"}},
|
|
|
|
}, "s1", "")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "t2", task.Name)
|
2020-06-22 17:55:59 +00:00
|
|
|
})
|
|
|
|
|
2020-07-08 15:19:36 +00:00
|
|
|
t.Run("infer ambiguous", func(t *testing.T) {
|
|
|
|
task, err := getNamedTaskForNativeService(&structs.TaskGroup{
|
|
|
|
Name: "g1",
|
|
|
|
Tasks: []*structs.Task{{Name: "t1"}, {Name: "t2"}},
|
|
|
|
}, "s1", "")
|
|
|
|
require.EqualError(t, err, "task for Consul Connect Native service g1->s1 is ambiguous and must be set")
|
|
|
|
require.Nil(t, task)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("named absent", func(t *testing.T) {
|
|
|
|
task, err := getNamedTaskForNativeService(&structs.TaskGroup{
|
|
|
|
Name: "g1",
|
|
|
|
Tasks: []*structs.Task{{Name: "t1"}, {Name: "t2"}},
|
|
|
|
}, "s1", "t3")
|
|
|
|
require.EqualError(t, err, "task t3 named by Consul Connect Native service g1->s1 does not exist")
|
|
|
|
require.Nil(t, task)
|
2020-06-22 17:55:59 +00:00
|
|
|
})
|
|
|
|
}
|
2020-07-28 20:12:08 +00:00
|
|
|
|
|
|
|
func TestJobEndpointConnect_groupConnectGatewayValidate(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
t.Run("no group network", func(t *testing.T) {
|
|
|
|
err := groupConnectGatewayValidate(&structs.TaskGroup{
|
|
|
|
Name: "g1",
|
|
|
|
Networks: nil,
|
|
|
|
})
|
|
|
|
require.EqualError(t, err, `Consul Connect gateways require exactly 1 network, found 0 in group "g1"`)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("bad network mode", func(t *testing.T) {
|
|
|
|
err := groupConnectGatewayValidate(&structs.TaskGroup{
|
|
|
|
Name: "g1",
|
|
|
|
Networks: structs.Networks{{
|
|
|
|
Mode: "",
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
require.EqualError(t, err, `Consul Connect Gateway service requires Task Group with network mode of type "bridge" or "host"`)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestJobEndpointConnect_newConnectGatewayTask_host(t *testing.T) {
|
2020-12-15 20:38:33 +00:00
|
|
|
t.Run("ingress", func(t *testing.T) {
|
|
|
|
task := newConnectGatewayTask(structs.ConnectIngressPrefix, "foo", true)
|
|
|
|
require.Equal(t, "connect-ingress-foo", task.Name)
|
|
|
|
require.Equal(t, "connect-ingress:foo", string(task.Kind))
|
|
|
|
require.Equal(t, ">= 1.8.0", task.Constraints[0].RTarget)
|
|
|
|
require.Equal(t, "host", task.Config["network_mode"])
|
|
|
|
require.Nil(t, task.Lifecycle)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("terminating", func(t *testing.T) {
|
|
|
|
task := newConnectGatewayTask(structs.ConnectTerminatingPrefix, "bar", true)
|
|
|
|
require.Equal(t, "connect-terminating-bar", task.Name)
|
|
|
|
require.Equal(t, "connect-terminating:bar", string(task.Kind))
|
|
|
|
require.Equal(t, ">= 1.8.0", task.Constraints[0].RTarget)
|
|
|
|
require.Equal(t, "host", task.Config["network_mode"])
|
|
|
|
require.Nil(t, task.Lifecycle)
|
|
|
|
})
|
2020-07-28 20:12:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestJobEndpointConnect_newConnectGatewayTask_bridge(t *testing.T) {
|
2020-12-15 20:38:33 +00:00
|
|
|
task := newConnectGatewayTask(structs.ConnectIngressPrefix, "service1", false)
|
2020-07-28 20:12:08 +00:00
|
|
|
require.NotContains(t, task.Config, "network_mode")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestJobEndpointConnect_hasGatewayTaskForService(t *testing.T) {
|
|
|
|
t.Run("no gateway task", func(t *testing.T) {
|
|
|
|
result := hasGatewayTaskForService(&structs.TaskGroup{
|
|
|
|
Name: "group",
|
|
|
|
Tasks: []*structs.Task{{
|
|
|
|
Name: "task1",
|
|
|
|
Kind: "",
|
|
|
|
}},
|
|
|
|
}, "my-service")
|
|
|
|
require.False(t, result)
|
|
|
|
})
|
|
|
|
|
2020-12-15 20:38:33 +00:00
|
|
|
t.Run("has ingress task", func(t *testing.T) {
|
2020-07-28 20:12:08 +00:00
|
|
|
result := hasGatewayTaskForService(&structs.TaskGroup{
|
|
|
|
Name: "group",
|
|
|
|
Tasks: []*structs.Task{{
|
|
|
|
Name: "ingress-gateway-my-service",
|
|
|
|
Kind: structs.NewTaskKind(structs.ConnectIngressPrefix, "my-service"),
|
|
|
|
}},
|
|
|
|
}, "my-service")
|
|
|
|
require.True(t, result)
|
|
|
|
})
|
2020-12-15 20:38:33 +00:00
|
|
|
|
|
|
|
t.Run("has terminating task", func(t *testing.T) {
|
|
|
|
result := hasGatewayTaskForService(&structs.TaskGroup{
|
|
|
|
Name: "group",
|
|
|
|
Tasks: []*structs.Task{{
|
|
|
|
Name: "terminating-gateway-my-service",
|
|
|
|
Kind: structs.NewTaskKind(structs.ConnectTerminatingPrefix, "my-service"),
|
|
|
|
}},
|
|
|
|
}, "my-service")
|
|
|
|
require.True(t, result)
|
|
|
|
})
|
2020-07-28 20:12:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestJobEndpointConnect_gatewayProxyIsDefault(t *testing.T) {
|
|
|
|
t.Run("nil", func(t *testing.T) {
|
|
|
|
result := gatewayProxyIsDefault(nil)
|
|
|
|
require.True(t, result)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("unrelated fields set", func(t *testing.T) {
|
|
|
|
result := gatewayProxyIsDefault(&structs.ConsulGatewayProxy{
|
2020-08-24 13:40:11 +00:00
|
|
|
ConnectTimeout: helper.TimeToPtr(2 * time.Second),
|
|
|
|
Config: map[string]interface{}{"foo": 1},
|
2020-07-28 20:12:08 +00:00
|
|
|
})
|
|
|
|
require.True(t, result)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("no-bind set", func(t *testing.T) {
|
|
|
|
result := gatewayProxyIsDefault(&structs.ConsulGatewayProxy{
|
|
|
|
EnvoyGatewayNoDefaultBind: true,
|
|
|
|
})
|
|
|
|
require.False(t, result)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("bind-tagged set", func(t *testing.T) {
|
|
|
|
result := gatewayProxyIsDefault(&structs.ConsulGatewayProxy{
|
|
|
|
EnvoyGatewayBindTaggedAddresses: true,
|
|
|
|
})
|
|
|
|
require.False(t, result)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("bind-addresses set", func(t *testing.T) {
|
|
|
|
result := gatewayProxyIsDefault(&structs.ConsulGatewayProxy{
|
|
|
|
EnvoyGatewayBindAddresses: map[string]*structs.ConsulGatewayBindAddress{
|
2020-12-14 22:41:14 +00:00
|
|
|
"listener1": {
|
2020-07-28 20:12:08 +00:00
|
|
|
Address: "1.1.1.1",
|
|
|
|
Port: 9000,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
require.False(t, result)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestJobEndpointConnect_gatewayBindAddresses(t *testing.T) {
|
|
|
|
t.Run("nil", func(t *testing.T) {
|
2020-12-15 20:38:33 +00:00
|
|
|
|
|
|
|
result := gatewayBindAddressesIngress(nil)
|
2021-01-22 14:18:17 +00:00
|
|
|
require.Empty(t, result)
|
2020-07-28 20:12:08 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("no listeners", func(t *testing.T) {
|
2020-12-15 20:38:33 +00:00
|
|
|
result := gatewayBindAddressesIngress(&structs.ConsulIngressConfigEntry{Listeners: nil})
|
2021-01-22 14:18:17 +00:00
|
|
|
require.Empty(t, result)
|
2020-07-28 20:12:08 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("simple", func(t *testing.T) {
|
2020-12-15 20:38:33 +00:00
|
|
|
result := gatewayBindAddressesIngress(&structs.ConsulIngressConfigEntry{
|
2020-07-28 20:12:08 +00:00
|
|
|
Listeners: []*structs.ConsulIngressListener{{
|
|
|
|
Port: 3000,
|
|
|
|
Protocol: "tcp",
|
|
|
|
Services: []*structs.ConsulIngressService{{
|
|
|
|
Name: "service1",
|
|
|
|
}},
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
require.Equal(t, map[string]*structs.ConsulGatewayBindAddress{
|
2020-12-14 22:41:14 +00:00
|
|
|
"service1": {
|
2020-07-28 20:12:08 +00:00
|
|
|
Address: "0.0.0.0",
|
|
|
|
Port: 3000,
|
|
|
|
},
|
|
|
|
}, result)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("complex", func(t *testing.T) {
|
2020-12-15 20:38:33 +00:00
|
|
|
result := gatewayBindAddressesIngress(&structs.ConsulIngressConfigEntry{
|
2020-07-28 20:12:08 +00:00
|
|
|
Listeners: []*structs.ConsulIngressListener{{
|
|
|
|
Port: 3000,
|
|
|
|
Protocol: "tcp",
|
|
|
|
Services: []*structs.ConsulIngressService{{
|
|
|
|
Name: "service1",
|
|
|
|
}, {
|
|
|
|
Name: "service2",
|
|
|
|
}},
|
|
|
|
}, {
|
|
|
|
Port: 3001,
|
|
|
|
Protocol: "http",
|
|
|
|
Services: []*structs.ConsulIngressService{{
|
|
|
|
Name: "service3",
|
|
|
|
}},
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
require.Equal(t, map[string]*structs.ConsulGatewayBindAddress{
|
2020-12-14 22:41:14 +00:00
|
|
|
"service1": {
|
2020-07-28 20:12:08 +00:00
|
|
|
Address: "0.0.0.0",
|
|
|
|
Port: 3000,
|
|
|
|
},
|
2020-12-14 22:41:14 +00:00
|
|
|
"service2": {
|
2020-07-28 20:12:08 +00:00
|
|
|
Address: "0.0.0.0",
|
|
|
|
Port: 3000,
|
|
|
|
},
|
2020-12-14 22:41:14 +00:00
|
|
|
"service3": {
|
2020-07-28 20:12:08 +00:00
|
|
|
Address: "0.0.0.0",
|
|
|
|
Port: 3001,
|
|
|
|
},
|
|
|
|
}, result)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestJobEndpointConnect_gatewayProxyForBridge(t *testing.T) {
|
|
|
|
t.Run("nil", func(t *testing.T) {
|
|
|
|
result := gatewayProxyForBridge(nil)
|
|
|
|
require.Nil(t, result)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("nil proxy", func(t *testing.T) {
|
|
|
|
result := gatewayProxyForBridge(&structs.ConsulGateway{
|
|
|
|
Ingress: &structs.ConsulIngressConfigEntry{
|
|
|
|
Listeners: []*structs.ConsulIngressListener{{
|
|
|
|
Port: 3000,
|
|
|
|
Protocol: "tcp",
|
|
|
|
Services: []*structs.ConsulIngressService{{
|
|
|
|
Name: "service1",
|
|
|
|
}},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
require.Equal(t, &structs.ConsulGatewayProxy{
|
2021-01-19 16:11:02 +00:00
|
|
|
ConnectTimeout: helper.TimeToPtr(defaultConnectTimeout),
|
2020-07-28 20:12:08 +00:00
|
|
|
EnvoyGatewayNoDefaultBind: true,
|
|
|
|
EnvoyGatewayBindTaggedAddresses: false,
|
|
|
|
EnvoyGatewayBindAddresses: map[string]*structs.ConsulGatewayBindAddress{
|
|
|
|
"service1": {
|
|
|
|
Address: "0.0.0.0",
|
|
|
|
Port: 3000,
|
|
|
|
}},
|
|
|
|
}, result)
|
|
|
|
})
|
|
|
|
|
2020-12-15 20:38:33 +00:00
|
|
|
t.Run("ingress set defaults", func(t *testing.T) {
|
2020-07-28 20:12:08 +00:00
|
|
|
result := gatewayProxyForBridge(&structs.ConsulGateway{
|
|
|
|
Proxy: &structs.ConsulGatewayProxy{
|
2020-08-24 13:40:11 +00:00
|
|
|
ConnectTimeout: helper.TimeToPtr(2 * time.Second),
|
|
|
|
Config: map[string]interface{}{"foo": 1},
|
2020-07-28 20:12:08 +00:00
|
|
|
},
|
|
|
|
Ingress: &structs.ConsulIngressConfigEntry{
|
|
|
|
Listeners: []*structs.ConsulIngressListener{{
|
|
|
|
Port: 3000,
|
|
|
|
Protocol: "tcp",
|
|
|
|
Services: []*structs.ConsulIngressService{{
|
|
|
|
Name: "service1",
|
|
|
|
}},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
require.Equal(t, &structs.ConsulGatewayProxy{
|
|
|
|
ConnectTimeout: helper.TimeToPtr(2 * time.Second),
|
|
|
|
Config: map[string]interface{}{"foo": 1},
|
|
|
|
EnvoyGatewayNoDefaultBind: true,
|
|
|
|
EnvoyGatewayBindTaggedAddresses: false,
|
|
|
|
EnvoyGatewayBindAddresses: map[string]*structs.ConsulGatewayBindAddress{
|
|
|
|
"service1": {
|
|
|
|
Address: "0.0.0.0",
|
|
|
|
Port: 3000,
|
|
|
|
}},
|
|
|
|
}, result)
|
|
|
|
})
|
|
|
|
|
2020-12-15 20:38:33 +00:00
|
|
|
t.Run("ingress leave as-is", func(t *testing.T) {
|
2020-07-28 20:12:08 +00:00
|
|
|
result := gatewayProxyForBridge(&structs.ConsulGateway{
|
|
|
|
Proxy: &structs.ConsulGatewayProxy{
|
|
|
|
Config: map[string]interface{}{"foo": 1},
|
|
|
|
EnvoyGatewayBindTaggedAddresses: true,
|
|
|
|
},
|
|
|
|
Ingress: &structs.ConsulIngressConfigEntry{
|
|
|
|
Listeners: []*structs.ConsulIngressListener{{
|
|
|
|
Port: 3000,
|
|
|
|
Protocol: "tcp",
|
|
|
|
Services: []*structs.ConsulIngressService{{
|
|
|
|
Name: "service1",
|
|
|
|
}},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
require.Equal(t, &structs.ConsulGatewayProxy{
|
|
|
|
Config: map[string]interface{}{"foo": 1},
|
|
|
|
EnvoyGatewayNoDefaultBind: false,
|
|
|
|
EnvoyGatewayBindTaggedAddresses: true,
|
|
|
|
EnvoyGatewayBindAddresses: nil,
|
|
|
|
}, result)
|
|
|
|
})
|
2020-12-15 20:38:33 +00:00
|
|
|
|
|
|
|
t.Run("terminating set defaults", func(t *testing.T) {
|
|
|
|
result := gatewayProxyForBridge(&structs.ConsulGateway{
|
|
|
|
Proxy: &structs.ConsulGatewayProxy{
|
|
|
|
ConnectTimeout: helper.TimeToPtr(2 * time.Second),
|
|
|
|
EnvoyDNSDiscoveryType: "STRICT_DNS",
|
|
|
|
},
|
|
|
|
Terminating: &structs.ConsulTerminatingConfigEntry{
|
|
|
|
Services: []*structs.ConsulLinkedService{{
|
|
|
|
Name: "service1",
|
|
|
|
CAFile: "/cafile.pem",
|
|
|
|
CertFile: "/certfile.pem",
|
|
|
|
KeyFile: "/keyfile.pem",
|
|
|
|
SNI: "",
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
require.Equal(t, &structs.ConsulGatewayProxy{
|
|
|
|
ConnectTimeout: helper.TimeToPtr(2 * time.Second),
|
|
|
|
EnvoyGatewayNoDefaultBind: true,
|
|
|
|
EnvoyGatewayBindTaggedAddresses: false,
|
|
|
|
EnvoyDNSDiscoveryType: "STRICT_DNS",
|
|
|
|
EnvoyGatewayBindAddresses: map[string]*structs.ConsulGatewayBindAddress{
|
|
|
|
"default": {
|
|
|
|
Address: "0.0.0.0",
|
|
|
|
Port: -1,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, result)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("terminating leave as-is", func(t *testing.T) {
|
|
|
|
//
|
|
|
|
})
|
2020-07-28 20:12:08 +00:00
|
|
|
}
|