Skip to content

Commit

Permalink
NetworksByPriority: ensure the sort order is stable
Browse files Browse the repository at this point in the history
NetworksByPriority calls sort.Slice() to sort the map of networks
attached to a given service by their respective priority. The
Priority property being non mandatory, it defaults to 0 when
unspecified.

The godoc for sort.Slice() specifies:

> The sort is not guaranteed to be stable: equal elements may be
> reversed from their original order. For a stable sort, use
> SliceStable.

SliceStable() won't work either, since NetworksByPriority has to
transform the map of networks into a list before calling
sort.Slice() -- Go makes no guarantee about the order of items in
a map.

The only way to guarantee a stable order is to fall back to
lexicographic sorting when two networks have the same priority. It
seems to be the best option as the compose-spec doesn't specify how
multiple network attachment referencing the same network should be
handled.

A regression test has been added.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
akerouanton authored and ndeloof committed Feb 17, 2024
1 parent 5ca9ef2 commit 758459d
Showing 2 changed files with 15 additions and 0 deletions.
3 changes: 3 additions & 0 deletions types/types.go
Original file line number Diff line number Diff line change
@@ -162,6 +162,9 @@ func (s *ServiceConfig) NetworksByPriority() []string {
})
}
sort.Slice(keys, func(i, j int) bool {
if keys[i].priority == keys[j].priority {
return keys[i].name < keys[j].name
}
return keys[i].priority > keys[j].priority
})
var sorted []string
12 changes: 12 additions & 0 deletions types/types_test.go
Original file line number Diff line number Diff line change
@@ -269,6 +269,18 @@ func TestNetworksByPriority(t *testing.T) {
assert.DeepEqual(t, s.NetworksByPriority(), []string{"qix", "zot", "bar", "foo"})
}

func TestNetworksByPriorityWithEqualPriorities(t *testing.T) {
s := ServiceConfig{
Networks: map[string]*ServiceNetworkConfig{
"foo": nil,
"bar": nil,
"zot": nil,
"qix": nil,
},
}
assert.DeepEqual(t, s.NetworksByPriority(), []string{"bar", "foo", "qix", "zot"})
}

func TestMarshalServiceEntrypoint(t *testing.T) {
t.Parallel()

0 comments on commit 758459d

Please sign in to comment.