-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix --network-add adding duplicate networks #780
Conversation
Didn't have a look yet at creating a unit-test for this (if we want one) |
Codecov Report
@@ Coverage Diff @@
## master #780 +/- ##
==========================================
+ Coverage 50.9% 52.22% +1.31%
==========================================
Files 237 237
Lines 15338 15342 +4
==========================================
+ Hits 7808 8012 +204
+ Misses 7028 6819 -209
- Partials 502 511 +9 |
hmm, not sure how this works. Isn't the problem in |
Yeah, basically
Each network set by However, that translation was not done for So on network create; {
"EndpointSpec": {
"Mode": "vip"
},
"Labels": {},
"Mode": {
"Replicated": {}
},
"Name": "bla",
"TaskTemplate": {
"ContainerSpec": {
"DNSConfig": {},
"Image": "nginx:alpine@sha256:40e95eef5082a5b26c5fd9441bd7ee6bcda1bb5f9fbf7a4a1ef9b2b0f88d5c43"
},
"ForceUpdate": 0,
"Networks": [
{
"Target": "foo"
}
],
"Placement": {
"Platforms": [
{
"Architecture": "amd64",
"OS": "linux"
}
]
},
"Resources": {
"Limits": {},
"Reservations": {}
}
}
} Then, on update, the spec is fetched from the daemon (which returns network ID's), but the added network is added to the spec by name, so this is sent on update: {
"EndpointSpec": {
"Mode": "vip"
},
"Labels": {},
"Mode": {
"Replicated": {
"Replicas": 1
}
},
"Name": "bla",
"TaskTemplate": {
"ContainerSpec": {
"DNSConfig": {},
"Image": "nginx:alpine@sha256:40e95eef5082a5b26c5fd9441bd7ee6bcda1bb5f9fbf7a4a1ef9b2b0f88d5c43"
},
"ForceUpdate": 0,
"Networks": [
{
"Target": "foo"
},
{
"Target": "x8bnlf8np4o8gk8nnh0ilg6oo"
}
],
"Placement": {
"Platforms": [
{
"Architecture": "amd64",
"OS": "linux"
}
]
},
"Resources": {
"Limits": {},
"Reservations": {}
},
"Runtime": "container"
}
} Where |
Ok, but the code that is changed here is for converting opts to the swarn spec, not specifically for update, right? Isn't the update logic in cli/command/service/update.go updateNetworks() ? So I'm wondering if this fix is maybe in the wrong place. |
Well, For cli/cli/command/service/update.go Lines 1101 to 1107 in 97b148b
Existing networks (in the spec) already have an ID (no name); cli/cli/command/service/update.go Lines 1111 to 1118 in 97b148b
For cli/cli/command/service/update.go Lines 1122 to 1126 in 97b148b
So this change will address both Alternatively, we move the |
It would be great to remove Thanks, I understand the change now. I missed that this was being called from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
A unit test for updateNetworks()
would be great, but unfortunately (due to all the "lookup by id nonsense") that is a lot more difficult than it should be.
It's should still be possible with a fakeClient that implements NetworkInspect()
I agree; looking at this again, I think moving the Given that this didn't make it for 18.01-rc1; let me change this to
I confirmed this bug already being in 17.09, so it's not new, so not super-urgent (and containers get only a single network assigned, so no duplicates there) |
9b19a8c
to
56d3fd9
Compare
@dnephin updated with the changes discussed, PTAL |
netAttach = append(netAttach, swarm.NetworkAttachmentConfig{ | ||
Target: net.Target, | ||
Aliases: net.Aliases, | ||
DriverOpts: net.DriverOpts, | ||
}) | ||
} | ||
sort.Sort(byNetworkTarget(netAttach)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved the sorting out of here as well, otherwise service create would sort by network name, and service update sorted by network ID
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
cli/command/service/opts.go
Outdated
if err != nil { | ||
return "", err | ||
} | ||
return nw.ID, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: the if is unnecessary since NetworkIsnpect
returns a struct not a pointer. It can be replaced by
return nw.ID, err
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, nice one! I'll add that change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done :)
When adding a network using `docker service update --network-add`, the new network was added by _name_. Existing entries in a service spec are listed by network ID, which resulted in the CLI not detecting duplicate entries for the same network. This patch changes the behavior to always use the network-ID, so that duplicate entries are correctly caught. Before this change; $ docker network create -d overlay foo $ docker service create --name=test --network=foo nginx:alpine $ docker service update --network-add foo test $ docker service inspect --format '{{ json .Spec.TaskTemplate.Networks}}' test [ { "Target": "9ot0ieagg5xv1gxd85m7y33eq" }, { "Target": "9ot0ieagg5xv1gxd85m7y33eq" } ] After this change: $ docker network create -d overlay foo $ docker service create --name=test --network=foo nginx:alpine $ docker service update --network-add foo test service is already attached to network foo Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
56d3fd9
to
e6ebaf5
Compare
ping @vdemeester PTAL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🐯
When adding a network using
docker service update --network-add
,the new network was added by name.
Existing entries in a service spec are listed by network ID, which
resulted in the CLI not detecting duplicate entries for the same
network.
This patch changes the behavior to always use the network-ID,
so that duplicate entries are correctly caught.
Before this change;
After this change:
$ docker network create -d overlay foo $ docker service create --name=test --network=foo nginx:alpine $ docker service update --network-add foo test service is already attached to network 9ot0ieagg5xv1gxd85m7y33eq
- Description for the changelog