diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b0a810c68f..8401d8e3e0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ IMPROVEMENTS: BUG FIXES: * client: Fixed a bug where clients configured with `cpu_total_compute` did not update the `cpu.totalcompute` node attribute. [[GH-9532](https://github.com/hashicorp/nomad/issues/9532)] + * core: Fixed a bug where an in place update dropped an allocations shared allocated resources [[GH-9736](https://github.com/hashicorp/nomad/issues/9736)] * consul: Fixed a bug where updating a task to include services would not work [[GH-9707](https://github.com/hashicorp/nomad/issues/9707)] * consul: Fixed alloc address mode port advertisement to use the mapped `to` port value [[GH-9730](https://github.com/hashicorp/nomad/issues/9730)] * consul/connect: Fixed a bug where absent ingress envoy proxy configuration could panic client [[GH-9669](https://github.com/hashicorp/nomad/issues/9669)] diff --git a/scheduler/util.go b/scheduler/util.go index 7261f67deb8..b42895a16b8 100644 --- a/scheduler/util.go +++ b/scheduler/util.go @@ -728,7 +728,9 @@ func inplaceUpdate(ctx Context, eval *structs.Evaluation, job *structs.Job, Tasks: option.TaskResources, TaskLifecycles: option.TaskLifecycles, Shared: structs.AllocatedSharedResources{ - DiskMB: int64(update.TaskGroup.EphemeralDisk.SizeMB), + DiskMB: int64(update.TaskGroup.EphemeralDisk.SizeMB), + Ports: update.Alloc.AllocatedResources.Shared.Ports, + Networks: update.Alloc.AllocatedResources.Shared.Networks.Copy(), }, } newAlloc.Metrics = ctx.Metrics() diff --git a/scheduler/util_test.go b/scheduler/util_test.go index 654b23f2424..7ca5255e67c 100644 --- a/scheduler/util_test.go +++ b/scheduler/util_test.go @@ -909,6 +909,63 @@ func TestInplaceUpdate_ChangedTaskGroup(t *testing.T) { require.Empty(t, ctx.plan.NodeAllocation, "inplaceUpdate incorrectly did an inplace update") } +func TestInplaceUpdate_AllocatedResources(t *testing.T) { + state, ctx := testContext(t) + eval := mock.Eval() + job := mock.Job() + + node := mock.Node() + require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node)) + + // Register an alloc + alloc := &structs.Allocation{ + Namespace: structs.DefaultNamespace, + ID: uuid.Generate(), + EvalID: eval.ID, + NodeID: node.ID, + JobID: job.ID, + Job: job, + AllocatedResources: &structs.AllocatedResources{ + Shared: structs.AllocatedSharedResources{ + Ports: structs.AllocatedPorts{ + { + Label: "api-port", + Value: 19910, + To: 8080, + }, + }, + }, + }, + DesiredStatus: structs.AllocDesiredStatusRun, + TaskGroup: "web", + } + alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources} + require.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID))) + require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc})) + + // Update TG to add a new service (inplace) + tg := job.TaskGroups[0] + tg.Services = []*structs.Service{ + { + Name: "tg-service", + }, + } + + updates := []allocTuple{{Alloc: alloc, TaskGroup: tg}} + stack := NewGenericStack(false, ctx) + + // Do the inplace update. + unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates) + + require.True(t, len(unplaced) == 0 && len(inplace) == 1, "inplaceUpdate incorrectly did not perform an inplace update") + require.NotEmpty(t, ctx.plan.NodeAllocation, "inplaceUpdate incorrectly did an inplace update") + require.NotEmpty(t, ctx.plan.NodeAllocation[node.ID][0].AllocatedResources.Shared.Ports) + + port, ok := ctx.plan.NodeAllocation[node.ID][0].AllocatedResources.Shared.Ports.Get("api-port") + require.True(t, ok) + require.Equal(t, 19910, port.Value) +} + func TestInplaceUpdate_NoMatch(t *testing.T) { state, ctx := testContext(t) eval := mock.Eval()