Skip to content

d/network: filter networks individually#50831

Closed
corhere wants to merge 1 commit intomoby:masterfrom
corhere:network-filter-loop
Closed

d/network: filter networks individually#50831
corhere wants to merge 1 commit intomoby:masterfrom
corhere:network-filter-loop

Conversation

@corhere
Copy link
Contributor

@corhere corhere commented Aug 27, 2025

- What I did
I improved the code to filter a list of networks by a predicate specified in an Engine API request. It is simpler, more readable, more future-proof and more efficient.

- How I did it
Internally a network is represented by either a libnetwork.Network or a swarmapi.Network. The daemon functions backing the API server map these values to the Engine API network.Inspect type on demand. Since they have to convert, the functions to get a list of networks have to loop over the slice of Networks and append them to a slice of network.Inspect values.

The function used to filter the list of networks by a user-supplied predicate takes a []network.Inspect and returns a shorter slice. Therefore the daemon functions backing the API server have to loop through the list twice; once to convert, and again inside the FilterNetworks function to prune networks from the slice. Each time an item is deleted from a slice, all items at higher indices need to be copied to lower indices in the backing array.

Replace FilterNetworks with a function that accepts a single network summary and returns a boolean. The daemon network-list functions can filter in the conversion loop, which cuts down on a nontrivial amount of copying. Split the validation of the filter predicate from filter evaluation to both make it more ergonomic to use inside loops, and to make invalid states (a filter with an ill-formed predicate) unrepresentable.

This change also future-proofs the network filter for when network.Inspect becomes a distinct type that embeds a network.Summary. Callers that need to build a filtered list of network.Inspect values will be able to evaluate the filter on the embedded Summary then append the full Inspect value of matching networks to the output slice, all without any further changes to the filter code.

- How to verify it
Existing unit/integration tests.

- Human readable description for the release notes

- A picture of a cute animal (not mandatory but encouraged)

@corhere corhere added this to the 29.0.0 milestone Aug 27, 2025
@corhere corhere added area/api API area/networking Networking kind/refactor PR's that refactor, or clean-up code labels Aug 27, 2025
@corhere corhere force-pushed the network-filter-loop branch 2 times, most recently from 3671109 to fe710e7 Compare August 28, 2025 17:24
Comment on lines +69 to +73
if f.args.Contains("idOrName") &&
!f.args.Match("name", nw.Name) &&
!f.args.Match("id", nw.Name) {
return false
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idOrName is not in the set of accepted filters for list-networks API requests. It is used internally, incorrectly:

filter := filters.NewArgs(filters.Arg("idOrName", term))

The net result is that when idOrName is in the filter, unless both name and id terms are also included it will always match due to the semantics of (filter.Args).Match returning true when the term is not present in the filter. And matching the id term against the container name is very suspicious. But that's what the old implementation also did, so this refactor maintains bug-for-bug compatibility.

Internally a network is represented by either a libnetwork.Network or a
swarmapi.Network. The daemon functions backing the API server map
these values to the Engine API network.Inspect type on demand. Since
they have to convert, the functions to get a list of networks have to
loop over the slice of Networks and append them to a slice of
network.Inspect values.

The function used to filter the list of networks by a user-supplied
predicate takes a []network.Inspect and returns a shorter slice.
Therefore the daemon functions backing the API server have to loop
through the list twice; once to convert, and again inside the
FilterNetworks function to prune networks from the slice. Each time an
item is deleted from a slice, all items at higher indices need to be
copied to lower indices in the backing array.

Replace FilterNetworks with a function that accepts a single network
summary and returns a boolean. The daemon network-list functions can
filter in the conversion loop, which cuts down on a nontrivial amount of
copying. Split the validation of the filter predicate from filter
evaluation to both make it more ergonomic to use inside loops, and to
make invalid states (a filter with an ill-formed predicate)
unrepresentable.

This change also future-proofs the network filter for when we change
network.Inspect to a distinct type that embeds a network.Summary.
Callers that need to build a filtered list of network.Inspect values
will be able to evaluate the filter on the embedded Summary then append
the full Inspect value of matching networks to the output slice.

Signed-off-by: Cory Snider <csnider@mirantis.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api API area/networking Networking kind/refactor PR's that refactor, or clean-up code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants