diff --git a/nomad/job_endpoint_test.go b/nomad/job_endpoint_test.go
index 6202a3ebf..fc065462d 100644
--- a/nomad/job_endpoint_test.go
+++ b/nomad/job_endpoint_test.go
@@ -5809,9 +5809,7 @@ func TestJobEndpoint_ValidateJob_ConsulConnect(t *testing.T) {
tg := j.TaskGroups[0]
tg.Services = tgServices
- tg.Networks = structs.Networks{
- {Mode: "bridge"},
- }
+ tg.Networks[0].Mode = "bridge"
err := validateJob(j)
require.NoError(t, err)
diff --git a/nomad/mock/mock.go b/nomad/mock/mock.go
index e8c555a10..2b2b4bbb6 100644
--- a/nomad/mock/mock.go
+++ b/nomad/mock/mock.go
@@ -209,6 +209,14 @@ func Job() *structs.Job {
DelayFunction: "constant",
},
Migrate: structs.DefaultMigrateStrategy(),
+ Networks: []*structs.NetworkResource{
+ {
+ DynamicPorts: []structs.Port{
+ {Label: "http"},
+ {Label: "admin"},
+ },
+ },
+ },
Tasks: []*structs.Task{
{
Name: "web",
@@ -244,15 +252,6 @@ func Job() *structs.Job {
Resources: &structs.Resources{
CPU: 500,
MemoryMB: 256,
- Networks: []*structs.NetworkResource{
- {
- MBits: 50,
- DynamicPorts: []structs.Port{
- {Label: "http"},
- {Label: "admin"},
- },
- },
- },
},
Meta: map[string]string{
"foo": "bar",
diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go
index d1a21df38..23277771c 100644
--- a/nomad/structs/structs.go
+++ b/nomad/structs/structs.go
@@ -6143,7 +6143,7 @@ func (tg *TaskGroup) Validate(j *Job) error {
}
}
- if err := task.Validate(tg.EphemeralDisk, j.Type, tg.Services); err != nil {
+ if err := task.Validate(tg.EphemeralDisk, j.Type, tg.Services, tg.Networks); err != nil {
outer := fmt.Errorf("Task %s validation failed: %v", task.Name, err)
mErr.Errors = append(mErr.Errors, outer)
}
@@ -6718,7 +6718,7 @@ func (t *Task) GoString() string {
}
// Validate is used to sanity check a task
-func (t *Task) Validate(ephemeralDisk *EphemeralDisk, jobType string, tgServices []*Service) error {
+func (t *Task) Validate(ephemeralDisk *EphemeralDisk, jobType string, tgServices []*Service, tgNetworks Networks) error {
var mErr multierror.Error
if t.Name == "" {
mErr.Errors = append(mErr.Errors, errors.New("Missing task name"))
@@ -6781,7 +6781,7 @@ func (t *Task) Validate(ephemeralDisk *EphemeralDisk, jobType string, tgServices
}
// Validate Services
- if err := validateServices(t); err != nil {
+ if err := validateServices(t, tgNetworks); err != nil {
mErr.Errors = append(mErr.Errors, err)
}
@@ -6879,7 +6879,7 @@ func (t *Task) Validate(ephemeralDisk *EphemeralDisk, jobType string, tgServices
// validateServices takes a task and validates the services within it are valid
// and reference ports that exist.
-func validateServices(t *Task) error {
+func validateServices(t *Task, tgNetworks Networks) error {
var mErr multierror.Error
// Ensure that services don't ask for nonexistent ports and their names are
@@ -6976,12 +6976,10 @@ func validateServices(t *Task) error {
// Get the set of port labels.
portLabels := make(map[string]struct{})
- if t.Resources != nil {
- for _, network := range t.Resources.Networks {
- ports := network.PortLabels()
- for portLabel := range ports {
- portLabels[portLabel] = struct{}{}
- }
+ if len(tgNetworks) > 0 {
+ ports := tgNetworks[0].PortLabels()
+ for portLabel := range ports {
+ portLabels[portLabel] = struct{}{}
}
}
diff --git a/nomad/structs/structs_test.go b/nomad/structs/structs_test.go
index ad8184336..995de79d4 100644
--- a/nomad/structs/structs_test.go
+++ b/nomad/structs/structs_test.go
@@ -1349,7 +1349,7 @@ func TestTaskGroupNetwork_Validate(t *testing.T) {
func TestTask_Validate(t *testing.T) {
task := &Task{}
ephemeralDisk := DefaultEphemeralDisk()
- err := task.Validate(ephemeralDisk, JobTypeBatch, nil)
+ err := task.Validate(ephemeralDisk, JobTypeBatch, nil, nil)
mErr := err.(*multierror.Error)
if !strings.Contains(mErr.Errors[0].Error(), "task name") {
t.Fatalf("err: %s", err)
@@ -1362,7 +1362,7 @@ func TestTask_Validate(t *testing.T) {
}
task = &Task{Name: "web/foo"}
- err = task.Validate(ephemeralDisk, JobTypeBatch, nil)
+ err = task.Validate(ephemeralDisk, JobTypeBatch, nil, nil)
mErr = err.(*multierror.Error)
if !strings.Contains(mErr.Errors[0].Error(), "slashes") {
t.Fatalf("err: %s", err)
@@ -1378,7 +1378,7 @@ func TestTask_Validate(t *testing.T) {
LogConfig: DefaultLogConfig(),
}
ephemeralDisk.SizeMB = 200
- err = task.Validate(ephemeralDisk, JobTypeBatch, nil)
+ err = task.Validate(ephemeralDisk, JobTypeBatch, nil, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
@@ -1392,7 +1392,7 @@ func TestTask_Validate(t *testing.T) {
LTarget: "${meta.rack}",
})
- err = task.Validate(ephemeralDisk, JobTypeBatch, nil)
+ err = task.Validate(ephemeralDisk, JobTypeBatch, nil, nil)
mErr = err.(*multierror.Error)
if !strings.Contains(mErr.Errors[0].Error(), "task level: distinct_hosts") {
t.Fatalf("err: %s", err)
@@ -1519,7 +1519,7 @@ func TestTask_Validate_Services(t *testing.T) {
Services: []*Service{s3, s4},
LogConfig: DefaultLogConfig(),
}
- task1.Resources.Networks = []*NetworkResource{
+ tgNetworks := []*NetworkResource{
{
MBits: 10,
DynamicPorts: []Port{
@@ -1535,7 +1535,7 @@ func TestTask_Validate_Services(t *testing.T) {
},
}
- err := task.Validate(ephemeralDisk, JobTypeService, nil)
+ err := task.Validate(ephemeralDisk, JobTypeService, nil, tgNetworks)
if err == nil {
t.Fatal("expected an error")
}
@@ -1556,7 +1556,7 @@ func TestTask_Validate_Services(t *testing.T) {
t.Fatalf("err: %v", err)
}
- if err = task1.Validate(ephemeralDisk, JobTypeService, nil); err != nil {
+ if err = task1.Validate(ephemeralDisk, JobTypeService, nil, tgNetworks); err != nil {
t.Fatalf("err : %v", err)
}
}
@@ -1571,18 +1571,18 @@ func TestTask_Validate_Service_AddressMode_Ok(t *testing.T) {
Services: []*Service{s},
LogConfig: DefaultLogConfig(),
}
- task.Resources.Networks = []*NetworkResource{
- {
- MBits: 10,
- DynamicPorts: []Port{
- {
- Label: "http",
- Value: 80,
- },
+
+ return task
+ }
+ tgNetworks := []*NetworkResource{
+ {
+ DynamicPorts: []Port{
+ {
+ Label: "http",
+ Value: 80,
},
},
- }
- return task
+ },
}
cases := []*Service{
@@ -1615,7 +1615,7 @@ func TestTask_Validate_Service_AddressMode_Ok(t *testing.T) {
for _, service := range cases {
task := getTask(service)
t.Run(service.Name, func(t *testing.T) {
- if err := task.Validate(ephemeralDisk, JobTypeService, nil); err != nil {
+ if err := task.Validate(ephemeralDisk, JobTypeService, nil, tgNetworks); err != nil {
t.Fatalf("unexpected err: %v", err)
}
})
@@ -1625,25 +1625,23 @@ func TestTask_Validate_Service_AddressMode_Ok(t *testing.T) {
func TestTask_Validate_Service_AddressMode_Bad(t *testing.T) {
ephemeralDisk := DefaultEphemeralDisk()
getTask := func(s *Service) *Task {
- task := &Task{
+ return &Task{
Name: "web",
Driver: "docker",
Resources: DefaultResources(),
Services: []*Service{s},
LogConfig: DefaultLogConfig(),
}
- task.Resources.Networks = []*NetworkResource{
- {
- MBits: 10,
- DynamicPorts: []Port{
- {
- Label: "http",
- Value: 80,
- },
+ }
+ tgNetworks := []*NetworkResource{
+ {
+ DynamicPorts: []Port{
+ {
+ Label: "http",
+ Value: 80,
},
},
- }
- return task
+ },
}
cases := []*Service{
@@ -1668,7 +1666,7 @@ func TestTask_Validate_Service_AddressMode_Bad(t *testing.T) {
for _, service := range cases {
task := getTask(service)
t.Run(service.Name, func(t *testing.T) {
- err := task.Validate(ephemeralDisk, JobTypeService, nil)
+ err := task.Validate(ephemeralDisk, JobTypeService, nil, tgNetworks)
if err == nil {
t.Fatalf("expected an error")
}
@@ -1785,9 +1783,10 @@ func TestTask_Validate_Service_Check(t *testing.T) {
// TestTask_Validate_Service_Check_AddressMode asserts that checks do not
// inherit address mode but do inherit ports.
func TestTask_Validate_Service_Check_AddressMode(t *testing.T) {
- getTask := func(s *Service) *Task {
+ getTask := func(s *Service) (*Task, *TaskGroup) {
return &Task{
- Resources: &Resources{
+ Services: []*Service{s},
+ }, &TaskGroup{
Networks: []*NetworkResource{
{
DynamicPorts: []Port{
@@ -1798,9 +1797,7 @@ func TestTask_Validate_Service_Check_AddressMode(t *testing.T) {
},
},
},
- },
- Services: []*Service{s},
- }
+ }
}
cases := []struct {
@@ -1939,9 +1936,9 @@ func TestTask_Validate_Service_Check_AddressMode(t *testing.T) {
for _, tc := range cases {
tc := tc
- task := getTask(tc.Service)
+ task, tg := getTask(tc.Service)
t.Run(tc.Service.Name, func(t *testing.T) {
- err := validateServices(task)
+ err := validateServices(task, tg.Networks)
if err == nil && tc.ErrContains == "" {
// Ok!
return
@@ -2097,7 +2094,7 @@ func TestTask_Validate_ConnectProxyKind(t *testing.T) {
task.Services = []*Service{tc.Service}
}
t.Run(tc.Desc, func(t *testing.T) {
- err := task.Validate(ephemeralDisk, "service", tc.TgService)
+ err := task.Validate(ephemeralDisk, "service", tc.TgService, nil)
if err == nil && tc.ErrContains == "" {
// Ok!
return
@@ -2116,7 +2113,7 @@ func TestTask_Validate_LogConfig(t *testing.T) {
SizeMB: 1,
}
- err := task.Validate(ephemeralDisk, JobTypeService, nil)
+ err := task.Validate(ephemeralDisk, JobTypeService, nil, nil)
mErr := err.(*multierror.Error)
if !strings.Contains(mErr.Errors[3].Error(), "log storage") {
t.Fatalf("err: %s", err)
@@ -2189,7 +2186,7 @@ func TestTask_Validate_CSIPluginConfig(t *testing.T) {
SizeMB: 1,
}
- err := task.Validate(ephemeralDisk, JobTypeService, nil)
+ err := task.Validate(ephemeralDisk, JobTypeService, nil, nil)
mErr := err.(*multierror.Error)
if tt.expectedErr != "" {
if !strings.Contains(mErr.Errors[4].Error(), tt.expectedErr) {
@@ -2214,7 +2211,7 @@ func TestTask_Validate_Template(t *testing.T) {
SizeMB: 1,
}
- err := task.Validate(ephemeralDisk, JobTypeService, nil)
+ err := task.Validate(ephemeralDisk, JobTypeService, nil, nil)
if !strings.Contains(err.Error(), "Template 1 validation failed") {
t.Fatalf("err: %s", err)
}
@@ -2227,7 +2224,7 @@ func TestTask_Validate_Template(t *testing.T) {
}
task.Templates = []*Template{good, good}
- err = task.Validate(ephemeralDisk, JobTypeService, nil)
+ err = task.Validate(ephemeralDisk, JobTypeService, nil, nil)
if !strings.Contains(err.Error(), "same destination as") {
t.Fatalf("err: %s", err)
}
@@ -2240,7 +2237,7 @@ func TestTask_Validate_Template(t *testing.T) {
},
}
- err = task.Validate(ephemeralDisk, JobTypeService, nil)
+ err = task.Validate(ephemeralDisk, JobTypeService, nil, nil)
if err == nil {
t.Fatalf("expected error from Template.Validate")
}
diff --git a/website/pages/docs/job-specification/network.mdx b/website/pages/docs/job-specification/network.mdx
index adb71ed66..fe3a2c5ed 100644
--- a/website/pages/docs/job-specification/network.mdx
+++ b/website/pages/docs/job-specification/network.mdx
@@ -46,7 +46,7 @@ job "docs" {
## `network` Parameters
-- `mbits` `([*deprecated*](/docs/upgrade/upgrade-specific#nomad-0-12-0) int: 10)` - Specifies the bandwidth required in MBits.
+- `mbits` ([*deprecated*](/docs/upgrade/upgrade-specific#nomad-0-12-0) int: 10) - Specifies the bandwidth required in MBits.
- `port` ([Port](#port-parameters): nil) - Specifies a TCP/UDP port
allocation and can be used to specify both dynamic ports and reserved ports.