diff --git a/nomad/structs/network.go b/nomad/structs/network.go index 33327a50b8a..1cbcce85572 100644 --- a/nomad/structs/network.go +++ b/nomad/structs/network.go @@ -95,11 +95,14 @@ func (idx *NetworkIndex) AddReserved(n *NetworkResource) (collide bool) { used = make(map[int]struct{}) idx.UsedPorts[n.IP] = used } - for _, port := range n.ReservedPorts { - if _, ok := used[port.Value]; ok { - collide = true - } else { - used[port.Value] = struct{}{} + + for _, ports := range [][]Port{n.ReservedPorts, n.DynamicPorts} { + for _, port := range ports { + if _, ok := used[port.Value]; ok { + collide = true + } else { + used[port.Value] = struct{}{} + } } } @@ -179,8 +182,11 @@ func (idx *NetworkIndex) AssignNetwork(ask *NetworkResource) (out *NetworkResour if _, ok := idx.UsedPorts[ipStr][randPort]; ok { goto PICK } - if isPortReserved(offer.ReservedPorts, randPort) { - goto PICK + + for _, ports := range [][]Port{offer.ReservedPorts, offer.DynamicPorts} { + if isPortReserved(ports, randPort) { + goto PICK + } } offer.DynamicPorts[i].Value = randPort } diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index d1c5c666d44..df7aa5f9ddd 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -645,6 +645,10 @@ func (n *NetworkResource) Copy() *NetworkResource { newR.ReservedPorts = make([]Port, len(n.ReservedPorts)) copy(newR.ReservedPorts, n.ReservedPorts) } + if n.DynamicPorts != nil { + newR.DynamicPorts = make([]Port, len(n.DynamicPorts)) + copy(newR.DynamicPorts, n.DynamicPorts) + } return newR } diff --git a/scheduler/generic_sched_test.go b/scheduler/generic_sched_test.go index e3e87557804..33abef8a498 100644 --- a/scheduler/generic_sched_test.go +++ b/scheduler/generic_sched_test.go @@ -60,6 +60,19 @@ func TestServiceSched_JobRegister(t *testing.T) { t.Fatalf("bad: %#v", out) } + // Ensure different ports were used. + used := make(map[int]struct{}) + for _, alloc := range out { + for _, resource := range alloc.TaskResources { + for _, port := range resource.Networks[0].DynamicPorts { + if _, ok := used[port.Value]; ok { + t.Fatalf("Port collision %v", port.Value) + } + used[port.Value] = struct{}{} + } + } + } + h.AssertEvalStatus(t, structs.EvalStatusComplete) }