Skip to content

Commit 0b0af85

Browse files
authored
Merge pull request #36316 from selansen/36247
Fix to address regression caused by PR 30897
2 parents 390b74c + 7cf8b20 commit 0b0af85

3 files changed

Lines changed: 88 additions & 4 deletions

File tree

daemon/cluster/executor/container/adapter.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
containertypes "github.com/docker/docker/api/types/container"
1919
"github.com/docker/docker/api/types/events"
2020
containerpkg "github.com/docker/docker/container"
21+
"github.com/docker/docker/daemon"
2122
"github.com/docker/docker/daemon/cluster/convert"
2223
executorpkg "github.com/docker/docker/daemon/cluster/executor"
2324
"github.com/docker/libnetwork"
@@ -155,7 +156,11 @@ func (c *containerAdapter) createNetworks(ctx context.Context) error {
155156
if _, ok := err.(libnetwork.NetworkNameError); ok {
156157
continue
157158
}
158-
159+
// We will continue if CreateManagedNetwork returns PredefinedNetworkError error.
160+
// Other callers still can treat it as Error.
161+
if _, ok := err.(daemon.PredefinedNetworkError); ok {
162+
continue
163+
}
159164
return err
160165
}
161166
}

daemon/network.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ import (
2424
"golang.org/x/net/context"
2525
)
2626

27+
// PredefinedNetworkError is returned when user tries to create predefined network that already exists.
28+
type PredefinedNetworkError string
29+
30+
func (pnr PredefinedNetworkError) Error() string {
31+
return fmt.Sprintf("operation is not permitted on predefined %s network ", string(pnr))
32+
}
33+
34+
// Forbidden denotes the type of this error
35+
func (pnr PredefinedNetworkError) Forbidden() {}
36+
2737
// NetworkControllerEnabled checks if the networking stack is enabled.
2838
// This feature depends on OS primitives and it's disabled in systems like Windows.
2939
func (daemon *Daemon) NetworkControllerEnabled() bool {
@@ -267,9 +277,8 @@ func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.N
267277
}
268278

269279
func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) {
270-
if runconfig.IsPreDefinedNetwork(create.Name) && !agent {
271-
err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name)
272-
return nil, errdefs.Forbidden(err)
280+
if runconfig.IsPreDefinedNetwork(create.Name) {
281+
return nil, PredefinedNetworkError(create.Name)
273282
}
274283

275284
var warning string
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package network // import "github.com/docker/docker/integration/network"
2+
3+
import (
4+
"runtime"
5+
"testing"
6+
"time"
7+
8+
"github.com/docker/docker/api/types"
9+
"github.com/docker/docker/api/types/filters"
10+
"github.com/docker/docker/api/types/swarm"
11+
"github.com/docker/docker/client"
12+
"github.com/gotestyourself/gotestyourself/poll"
13+
"github.com/stretchr/testify/require"
14+
"golang.org/x/net/context"
15+
)
16+
17+
func TestServiceWithPredefinedNetwork(t *testing.T) {
18+
defer setupTest(t)()
19+
d := newSwarm(t)
20+
defer d.Stop(t)
21+
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
22+
require.NoError(t, err)
23+
24+
hostName := "host"
25+
var instances uint64 = 1
26+
serviceName := "TestService"
27+
serviceSpec := swarmServiceSpec(serviceName, instances)
28+
serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: hostName})
29+
30+
serviceResp, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
31+
QueryRegistry: false,
32+
})
33+
require.NoError(t, err)
34+
35+
pollSettings := func(config *poll.Settings) {
36+
if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
37+
config.Timeout = 50 * time.Second
38+
config.Delay = 100 * time.Millisecond
39+
}
40+
}
41+
42+
serviceID := serviceResp.ID
43+
poll.WaitOn(t, serviceRunningCount(client, serviceID, instances), pollSettings)
44+
45+
_, _, err = client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
46+
require.NoError(t, err)
47+
48+
err = client.ServiceRemove(context.Background(), serviceID)
49+
require.NoError(t, err)
50+
51+
poll.WaitOn(t, serviceIsRemoved(client, serviceID), pollSettings)
52+
poll.WaitOn(t, noTasks(client), pollSettings)
53+
54+
}
55+
56+
func serviceRunningCount(client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result {
57+
return func(log poll.LogT) poll.Result {
58+
filter := filters.NewArgs()
59+
filter.Add("service", serviceID)
60+
services, err := client.ServiceList(context.Background(), types.ServiceListOptions{})
61+
if err != nil {
62+
return poll.Error(err)
63+
}
64+
65+
if len(services) != int(instances) {
66+
return poll.Continue("Service count at %d waiting for %d", len(services), instances)
67+
}
68+
return poll.Success()
69+
}
70+
}

0 commit comments

Comments
 (0)