Skip to content

Commit

Permalink
[f-gh-208] Force recreation and redeployment of task if volume label …
Browse files Browse the repository at this point in the history
…changes (#20074)

Scheduler: Force recreation and redeployment of task if volume mount labels in the task definitions changes
  • Loading branch information
Juanadelacuesta authored Mar 27, 2024
1 parent bd2a809 commit c7e7fdf
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
5 changes: 5 additions & 0 deletions nomad/structs/volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,11 @@ type VolumeMount struct {
SELinuxLabel string
}

// Hash is a very basic string based implementation of a hasher.
func (v *VolumeMount) Hash() string {
return fmt.Sprintf("%#+v", v)
}

func (v *VolumeMount) Equal(o *VolumeMount) bool {
if v == nil || o == nil {
return v == o
Expand Down
32 changes: 32 additions & 0 deletions scheduler/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

log "github.com/hashicorp/go-hclog"
memdb "github.com/hashicorp/go-memdb"
"github.com/hashicorp/go-set/v2"
"github.com/hashicorp/nomad/helper"
"github.com/hashicorp/nomad/nomad/structs"
)
Expand Down Expand Up @@ -334,6 +335,11 @@ func tasksUpdated(jobA, jobB *structs.Job, taskGroup string) comparison {
return difference("task log disabled", at.LogConfig.Disabled, bt.LogConfig.Disabled)
}

// Check volume mount updates
if c := volumeMountsUpdated(at.VolumeMounts, bt.VolumeMounts); c.modified {
return c
}

// Check if restart.render_templates is updated
if c := renderTemplatesUpdated(at.RestartPolicy, bt.RestartPolicy,
"task restart render_templates"); c.modified {
Expand Down Expand Up @@ -424,6 +430,32 @@ func connectServiceUpdated(servicesA, servicesB []*structs.Service) comparison {
return same
}

func volumeMountsUpdated(a, b []*structs.VolumeMount) comparison {
setA := set.HashSetFrom(a)
setB := set.HashSetFrom(b)

if setA.Equal(setB) {
return same
}

return difference("volume mounts", a, b)
}

// volumeMountUpdated returns true if the definition of the volume mount
// has been updated in a manner that will requires the task to be recreated.
func volumeMountUpdated(mountA, mountB *structs.VolumeMount) comparison {
if mountA != nil && mountB == nil {
difference("volume mount removed", mountA, mountB)
}

if mountA != nil && mountB != nil &&
mountA.SELinuxLabel != mountB.SELinuxLabel {
return difference("volume mount selinux label", mountA.SELinuxLabel, mountB.SELinuxLabel)
}

return same
}

// connectUpdated returns true if the connect block has been updated in a manner
// that will require a destructive update.
//
Expand Down
36 changes: 36 additions & 0 deletions scheduler/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,42 @@ func TestTasksUpdated(t *testing.T) {
// Compare changed Template ErrMissingKey
j30.TaskGroups[0].Tasks[0].Templates[0].ErrMissingKey = true
must.True(t, tasksUpdated(j29, j30, name).modified)

// Compare identical volume mounts
j31 := mock.Job()
j32 := j31.Copy()

must.False(t, tasksUpdated(j31, j32, name).modified)

// Modify volume mounts
j31.TaskGroups[0].Tasks[0].VolumeMounts = []*structs.VolumeMount{
{
Volume: "myvolume",
SELinuxLabel: "z",
},
}

j32.TaskGroups[0].Tasks[0].VolumeMounts = []*structs.VolumeMount{
{
Volume: "myvolume",
SELinuxLabel: "",
},
}

must.True(t, tasksUpdated(j31, j32, name).modified)

// Add volume mount
j32.TaskGroups[0].Tasks[0].VolumeMounts = append(j32.TaskGroups[0].Tasks[0].VolumeMounts,
&structs.VolumeMount{
Volume: "myvolume2",
SELinuxLabel: "Z",
})

// Remove volume mount
j32 = j31.Copy()
j32.TaskGroups[0].Tasks[0].VolumeMounts = nil

must.True(t, tasksUpdated(j31, j32, name).modified)
}

func TestTasksUpdated_connectServiceUpdated(t *testing.T) {
Expand Down

0 comments on commit c7e7fdf

Please sign in to comment.