Skip to content
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

Update FindNetwork to address network name duplications#30897

Merged
merged 2 commits into from
Jan 10, 2018

Conversation

yongtang
Copy link
Member

- What I did
This fix is part of the effort to address #30242 (comment) where issue arise when creating services because of the fact that multiple networks may share the same name (within or across local/swarm scopes).

- How I did it

The focus of this fix is to allow creation of service when a network in local scope has the same name as the service network.

- How to verify it

An integration test has been added.

- Description for the changelog

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

This fix is related to #30242.

Signed-off-by: Yong Tang yong.tang.github@outlook.com

@@ -15,6 +15,6 @@ type Backend interface {
CreateNetwork(nc types.NetworkCreateRequest) (*types.NetworkCreateResponse, error)
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error
DeleteNetwork(name string) error
DeleteNetwork(networkID string) error
Copy link
Member Author

Choose a reason for hiding this comment

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

Change to networkID to enforcing the usage of ID instead of Name/ID/Prefix

@@ -208,7 +139,12 @@ func (n *networkRouter) postNetworkConnect(ctx context.Context, w http.ResponseW
return err
}

return n.backend.ConnectContainerToNetwork(connect.Container, vars["id"], connect.EndpointConfig)
// Always make sure there is no ambiguity with respect to the network ID/name
Copy link
Member Author

Choose a reason for hiding this comment

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

It is a lot easier to enforcing non-ambiguity here.

@@ -225,22 +161,31 @@ func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.Respon
return err
}

return n.backend.DisconnectContainerFromNetwork(disconnect.Container, vars["id"], disconnect.Force)
// Always make sure there is no ambiguity with respect to the network ID/name
nw, err := n.backend.FindNetwork(vars["id"])
Copy link
Member Author

Choose a reason for hiding this comment

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

Non-ambiguity at the api level.

if err != nil {
return err
}
return n.backend.ConnectContainerToNetwork(connect.Container, nw.ID(), connect.EndpointConfig)
Copy link
Member Author

Choose a reason for hiding this comment

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

Pass nw.ID() for connect.

if err != nil {
return err
}
return n.backend.DisconnectContainerFromNetwork(disconnect.Container, nw.ID(), disconnect.Force)
Copy link
Member Author

Choose a reason for hiding this comment

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

Pass nw.ID() for disconnect.

return err
}
} else {
if err := n.backend.DeleteNetwork(nw.ID); err != nil {
Copy link
Member Author

Choose a reason for hiding this comment

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

Delete might happen in both local and scoped networks.

@@ -412,3 +357,82 @@ func (n *networkRouter) postNetworksPrune(ctx context.Context, w http.ResponseWr
}
return httputils.WriteJSON(w, http.StatusOK, pruneReport)
}

func (n *networkRouter) findNetwork(term string) (types.NetworkResource, error) {
// NOTE: This findNetwork is differnt from FindNetwork from the daemon.
Copy link
Member Author

Choose a reason for hiding this comment

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

This findNetwork is different from daemon.FindNetwork as it will be cross scopes (both local and swarm).

Copy link
Member

Choose a reason for hiding this comment

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

Could you make this comment a docstring (above the function) ? Right now it looks like it's documenting the variables inside the function.

Also what do you think about findUniqueNetwork() as a name?

Copy link
Member Author

@yongtang yongtang Apr 4, 2017

Choose a reason for hiding this comment

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

Thanks @dnephin. The comment has been updated to doc string. The name has also been changed.

// networks returns a list of network names attached to the container. The
// returned name can be used to lookup the corresponding network create
// options.
func (c *containerConfig) networks() []string {
Copy link
Member Author

Choose a reason for hiding this comment

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

The networks() is returning the name only, which should not be encouraged (should always use ID if possible).

@@ -1053,3 +1050,10 @@ func (daemon *Daemon) DeactivateContainerServiceBinding(containerName string) er
}
return sb.DisableService()
}

func getNetworkID(name string, endpointSettings *networktypes.EndpointSettings) string {
Copy link
Member Author

Choose a reason for hiding this comment

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

Alway try to use NetworkID whenever NetworkID is available.

Copy link
Member

Choose a reason for hiding this comment

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

This name is a bit odd (from just the name, I would expect it to always return an ID), not a big thing because it's not exported, but perhaps we should find a better name for it

@@ -249,7 +267,9 @@ func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string
}
if nw != nil {
if create.CheckDuplicate {
return nil, libnetwork.NetworkNameError(create.Name)
if !agent || nw.Info().Dynamic() {
Copy link
Member Author

Choose a reason for hiding this comment

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

In case of swarm networks, we have to allow creation even if a local network with the same name already exist.

@yongtang
Copy link
Member Author

The Jenkins failure seems real. Will spend time to investigate it.

@yongtang yongtang changed the title Update FindNetwork to address network name duplications [WIP] Update FindNetwork to address network name duplications Feb 10, 2017
@yongtang yongtang force-pushed the 30242-network-duplicate-names branch 2 times, most recently from 5666f16 to a2bfaab Compare February 11, 2017 03:24
@yongtang yongtang changed the title [WIP] Update FindNetwork to address network name duplications Update FindNetwork to address network name duplications Feb 11, 2017
@yongtang
Copy link
Member Author

All tests passed now.

@vdemeester
Copy link
Member

Copy link
Member

@dnephin dnephin left a comment

Choose a reason for hiding this comment

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

There seem to be a bunch of changes to DeleteNetwork.

Could you give more of an explanation of what this changes, and why it fixes the problem?

id2 := createNetwork(c, configNotCheck, true)

deleteNetwork(c, id1, true)
deleteNetwork(c, id2, true)
Copy link
Member

@dnephin dnephin Mar 9, 2017

Choose a reason for hiding this comment

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

Should these be defer, and called immediately after the create for each?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks. The PR has been updated.

@yongtang yongtang force-pushed the 30242-network-duplicate-names branch from a2bfaab to 7295c58 Compare March 10, 2017 00:15
@yongtang
Copy link
Member Author

yongtang commented Mar 10, 2017

Thanks @dnephin for the review. The goal of this PR is to try to address the issue caused by name duplication in network names.

Previously, the network name is unique so some of the implementation uses will look up the network name (instead of network ID) when needed.

However, later on the flag checkDuplicate was introduced and it is possible now to have multiple networks with the same name (the IDs are still unique) if checkDuplicate is false.

Adding swarm network in, the same network name could appears in either local or swarm scope. And even in the same scope (like swarm scope), the same network name could be referring to different network IDs.

However, in the existing implementation, many places uses FindNetwork to lookup a network based on the network name (unfortunately).

That causes issues:

  1. When deleting a network with a name, it may not always delete the same network.
  2. In swarm network, deploy a service may fail (see daemon allows creating two network with same name when checkDuplicate is false, REASONABLE? #30242 (comment)) because the network ID passed at the beginning may be referring to another network ID when service deployment is actually executed on an individual node. As a result, service deployment is always attempting because it incorrectly believe the requested network is not available yet.

This PR tries to address the issue mentioned by always avoid FindNetwork and use network ID for look up if possible (so that the network referred is unique and consistent).

case len(listByFullName) == 1:
return listByFullName[0], nil
case len(listByFullName) > 1:
return nil, fmt.Errorf("network %s is ambiguous (%d matches found based on name)", term, len(listByFullName))
Copy link
Member

@cpuguy83 cpuguy83 Jan 10, 2018

Choose a reason for hiding this comment

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

We should not be using fmt.Errorf for these errors.

Copy link
Member Author

Choose a reason for hiding this comment

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

@cpuguy83 Sorry, that was probably due to the multiple rebase/conflict that was overlooked. Let me take a look and have a fix for it.

Copy link
Member

Choose a reason for hiding this comment

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

No worries. I've got it fixed in my errdefs or.

@@ -12,11 +12,11 @@ import (
// Backend is all the methods that need to be implemented
// to provide network specific functionality.
type Backend interface {
FindNetwork(idName string) (libnetwork.Network, error)
FindUniqueNetwork(idName string) (libnetwork.Network, error)
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we should've kept the old name here (FindNetwork); the issue being resolved here is a bugfix, so I don't see a real reason to rename the function (in general, I'd expect a function like this to return a unique network, so not sure a change in naming is really needed)

@yongtang @vdemeester wdyt?

silvin-lubecki pushed a commit to silvin-lubecki/engine-extract that referenced this pull request Mar 16, 2020
This fix tries to add a `scope` in the query of `/networks/<id>`
(`NetworkInspect`) so that in case of duplicate network names,
it is possible to locate the network ID based on the network
scope (`local`, 'swarm', or `global`).

Multiple networks might exist in different scopes, which is a legitimate case.
For example, a network name `foo` might exists locally and in swarm network.

However, before this PR it was not possible to query a network name `foo`
in a specific scope like swarm.

This fix fixes the issue by allowing a `scope` query in `/networks/<id>`.

Additional test cases have been added to unit tests and integration tests.

This fix is related to docker/cli#167, moby/moby#30897, moby/moby#33561, moby/moby#30242

This fix fixes docker/cli#167

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
Upstream-commit: 158b2a1
Component: engine
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants