Fix to address regression caused by PR 30897
With the inclusion of PR 30897, creating service for host network fails in 18.02. Modified IsPreDefinedNetwork check and return NetworkNameError instead of errdefs.Forbidden to address this issue Signed-off-by: selansen <elango.siva@docker.com>
This commit is contained in:
parent
7459e4cd4f
commit
7cf8b20762
|
@ -18,6 +18,7 @@ import (
|
|||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
containerpkg "github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon"
|
||||
"github.com/docker/docker/daemon/cluster/convert"
|
||||
executorpkg "github.com/docker/docker/daemon/cluster/executor"
|
||||
"github.com/docker/libnetwork"
|
||||
|
@ -155,7 +156,11 @@ func (c *containerAdapter) createNetworks(ctx context.Context) error {
|
|||
if _, ok := err.(libnetwork.NetworkNameError); ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// We will continue if CreateManagedNetwork returns PredefinedNetworkError error.
|
||||
// Other callers still can treat it as Error.
|
||||
if _, ok := err.(daemon.PredefinedNetworkError); ok {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,16 @@ import (
|
|||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// PredefinedNetworkError is returned when user tries to create predefined network that already exists.
|
||||
type PredefinedNetworkError string
|
||||
|
||||
func (pnr PredefinedNetworkError) Error() string {
|
||||
return fmt.Sprintf("operation is not permitted on predefined %s network ", string(pnr))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (pnr PredefinedNetworkError) Forbidden() {}
|
||||
|
||||
// NetworkControllerEnabled checks if the networking stack is enabled.
|
||||
// This feature depends on OS primitives and it's disabled in systems like Windows.
|
||||
func (daemon *Daemon) NetworkControllerEnabled() bool {
|
||||
|
@ -267,9 +277,8 @@ func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.N
|
|||
}
|
||||
|
||||
func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) {
|
||||
if runconfig.IsPreDefinedNetwork(create.Name) && !agent {
|
||||
err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name)
|
||||
return nil, errdefs.Forbidden(err)
|
||||
if runconfig.IsPreDefinedNetwork(create.Name) {
|
||||
return nil, PredefinedNetworkError(create.Name)
|
||||
}
|
||||
|
||||
var warning string
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
package network // import "github.com/docker/docker/integration/network"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestServiceWithPredefinedNetwork(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
d := newSwarm(t)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
require.NoError(t, err)
|
||||
|
||||
hostName := "host"
|
||||
var instances uint64 = 1
|
||||
serviceName := "TestService"
|
||||
serviceSpec := swarmServiceSpec(serviceName, instances)
|
||||
serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: hostName})
|
||||
|
||||
serviceResp, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
|
||||
QueryRegistry: false,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
pollSettings := func(config *poll.Settings) {
|
||||
if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
|
||||
config.Timeout = 50 * time.Second
|
||||
config.Delay = 100 * time.Millisecond
|
||||
}
|
||||
}
|
||||
|
||||
serviceID := serviceResp.ID
|
||||
poll.WaitOn(t, serviceRunningCount(client, serviceID, instances), pollSettings)
|
||||
|
||||
_, _, err = client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = client.ServiceRemove(context.Background(), serviceID)
|
||||
require.NoError(t, err)
|
||||
|
||||
poll.WaitOn(t, serviceIsRemoved(client, serviceID), pollSettings)
|
||||
poll.WaitOn(t, noTasks(client), pollSettings)
|
||||
|
||||
}
|
||||
|
||||
func serviceRunningCount(client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
filter := filters.NewArgs()
|
||||
filter.Add("service", serviceID)
|
||||
services, err := client.ServiceList(context.Background(), types.ServiceListOptions{})
|
||||
if err != nil {
|
||||
return poll.Error(err)
|
||||
}
|
||||
|
||||
if len(services) != int(instances) {
|
||||
return poll.Continue("Service count at %d waiting for %d", len(services), instances)
|
||||
}
|
||||
return poll.Success()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue