github.com/LazyboyChen7/engine@v17.12.1-ce-rc2+incompatible/integration/network/inspect_test.go (about)

     1  package network
     2  
     3  import (
     4  	"fmt"
     5  	"runtime"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/docker/docker/api/types"
    10  	"github.com/docker/docker/api/types/filters"
    11  	"github.com/docker/docker/api/types/swarm"
    12  	"github.com/docker/docker/client"
    13  	"github.com/docker/docker/integration-cli/daemon"
    14  	"github.com/docker/docker/integration-cli/request"
    15  	"github.com/gotestyourself/gotestyourself/poll"
    16  	"github.com/stretchr/testify/require"
    17  	"golang.org/x/net/context"
    18  )
    19  
    20  const defaultSwarmPort = 2477
    21  const dockerdBinary = "dockerd"
    22  
    23  func TestInspectNetwork(t *testing.T) {
    24  	defer setupTest(t)()
    25  	d := newSwarm(t)
    26  	defer d.Stop(t)
    27  	client, err := request.NewClientForHost(d.Sock())
    28  	require.NoError(t, err)
    29  
    30  	overlayName := "overlay1"
    31  	networkCreate := types.NetworkCreate{
    32  		CheckDuplicate: true,
    33  		Driver:         "overlay",
    34  	}
    35  
    36  	netResp, err := client.NetworkCreate(context.Background(), overlayName, networkCreate)
    37  	require.NoError(t, err)
    38  	overlayID := netResp.ID
    39  
    40  	var instances uint64 = 4
    41  	serviceName := "TestService"
    42  	serviceSpec := swarmServiceSpec(serviceName, instances)
    43  	serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: overlayName})
    44  
    45  	serviceResp, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
    46  		QueryRegistry: false,
    47  	})
    48  	require.NoError(t, err)
    49  
    50  	pollSettings := func(config *poll.Settings) {
    51  		if runtime.GOARCH == "arm" {
    52  			config.Timeout = 30 * time.Second
    53  			config.Delay = 100 * time.Millisecond
    54  		}
    55  	}
    56  
    57  	serviceID := serviceResp.ID
    58  	poll.WaitOn(t, serviceRunningTasksCount(client, serviceID, instances), pollSettings)
    59  
    60  	_, _, err = client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
    61  	require.NoError(t, err)
    62  
    63  	// Test inspect verbose with full NetworkID
    64  	networkVerbose, err := client.NetworkInspect(context.Background(), overlayID, types.NetworkInspectOptions{
    65  		Verbose: true,
    66  	})
    67  	require.NoError(t, err)
    68  	require.True(t, validNetworkVerbose(networkVerbose, serviceName, instances))
    69  
    70  	// Test inspect verbose with partial NetworkID
    71  	networkVerbose, err = client.NetworkInspect(context.Background(), overlayID[0:11], types.NetworkInspectOptions{
    72  		Verbose: true,
    73  	})
    74  	require.NoError(t, err)
    75  	require.True(t, validNetworkVerbose(networkVerbose, serviceName, instances))
    76  
    77  	// Test inspect verbose with Network name and swarm scope
    78  	networkVerbose, err = client.NetworkInspect(context.Background(), overlayName, types.NetworkInspectOptions{
    79  		Verbose: true,
    80  		Scope:   "swarm",
    81  	})
    82  	require.NoError(t, err)
    83  	require.True(t, validNetworkVerbose(networkVerbose, serviceName, instances))
    84  
    85  	err = client.ServiceRemove(context.Background(), serviceID)
    86  	require.NoError(t, err)
    87  
    88  	poll.WaitOn(t, serviceIsRemoved(client, serviceID), pollSettings)
    89  	poll.WaitOn(t, noTasks(client), pollSettings)
    90  
    91  	serviceResp, err = client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
    92  		QueryRegistry: false,
    93  	})
    94  	require.NoError(t, err)
    95  
    96  	serviceID2 := serviceResp.ID
    97  	poll.WaitOn(t, serviceRunningTasksCount(client, serviceID2, instances), pollSettings)
    98  
    99  	err = client.ServiceRemove(context.Background(), serviceID2)
   100  	require.NoError(t, err)
   101  
   102  	poll.WaitOn(t, serviceIsRemoved(client, serviceID2), pollSettings)
   103  	poll.WaitOn(t, noTasks(client), pollSettings)
   104  
   105  	err = client.NetworkRemove(context.Background(), overlayID)
   106  	require.NoError(t, err)
   107  
   108  	poll.WaitOn(t, networkIsRemoved(client, overlayID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
   109  }
   110  
   111  func newSwarm(t *testing.T) *daemon.Swarm {
   112  	d := &daemon.Swarm{
   113  		Daemon: daemon.New(t, "", dockerdBinary, daemon.Config{
   114  			Experimental: testEnv.DaemonInfo.ExperimentalBuild,
   115  		}),
   116  		// TODO: better method of finding an unused port
   117  		Port: defaultSwarmPort,
   118  	}
   119  	// TODO: move to a NewSwarm constructor
   120  	d.ListenAddr = fmt.Sprintf("0.0.0.0:%d", d.Port)
   121  
   122  	// avoid networking conflicts
   123  	args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"}
   124  	d.StartWithBusybox(t, args...)
   125  
   126  	require.NoError(t, d.Init(swarm.InitRequest{}))
   127  	return d
   128  }
   129  
   130  func swarmServiceSpec(name string, replicas uint64) swarm.ServiceSpec {
   131  	return swarm.ServiceSpec{
   132  		Annotations: swarm.Annotations{
   133  			Name: name,
   134  		},
   135  		TaskTemplate: swarm.TaskSpec{
   136  			ContainerSpec: &swarm.ContainerSpec{
   137  				Image:   "busybox:latest",
   138  				Command: []string{"/bin/top"},
   139  			},
   140  		},
   141  		Mode: swarm.ServiceMode{
   142  			Replicated: &swarm.ReplicatedService{
   143  				Replicas: &replicas,
   144  			},
   145  		},
   146  	}
   147  }
   148  
   149  func serviceRunningTasksCount(client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result {
   150  	return func(log poll.LogT) poll.Result {
   151  		filter := filters.NewArgs()
   152  		filter.Add("service", serviceID)
   153  		tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
   154  			Filters: filter,
   155  		})
   156  		switch {
   157  		case err != nil:
   158  			return poll.Error(err)
   159  		case len(tasks) == int(instances):
   160  			for _, task := range tasks {
   161  				if task.Status.State != swarm.TaskStateRunning {
   162  					return poll.Continue("waiting for tasks to enter run state")
   163  				}
   164  			}
   165  			return poll.Success()
   166  		default:
   167  			return poll.Continue("task count at %d waiting for %d", len(tasks), instances)
   168  		}
   169  	}
   170  }
   171  
   172  func networkIsRemoved(client client.NetworkAPIClient, networkID string) func(log poll.LogT) poll.Result {
   173  	return func(log poll.LogT) poll.Result {
   174  		_, err := client.NetworkInspect(context.Background(), networkID, types.NetworkInspectOptions{})
   175  		if err == nil {
   176  			return poll.Continue("waiting for network %s to be removed", networkID)
   177  		}
   178  		return poll.Success()
   179  	}
   180  }
   181  
   182  func serviceIsRemoved(client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result {
   183  	return func(log poll.LogT) poll.Result {
   184  		filter := filters.NewArgs()
   185  		filter.Add("service", serviceID)
   186  		_, err := client.TaskList(context.Background(), types.TaskListOptions{
   187  			Filters: filter,
   188  		})
   189  		if err == nil {
   190  			return poll.Continue("waiting for service %s to be deleted", serviceID)
   191  		}
   192  		return poll.Success()
   193  	}
   194  }
   195  
   196  func noTasks(client client.ServiceAPIClient) func(log poll.LogT) poll.Result {
   197  	return func(log poll.LogT) poll.Result {
   198  		filter := filters.NewArgs()
   199  		tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
   200  			Filters: filter,
   201  		})
   202  		switch {
   203  		case err != nil:
   204  			return poll.Error(err)
   205  		case len(tasks) == 0:
   206  			return poll.Success()
   207  		default:
   208  			return poll.Continue("task count at %d waiting for 0", len(tasks))
   209  		}
   210  	}
   211  }
   212  
   213  // Check to see if Service and Tasks info are part of the inspect verbose response
   214  func validNetworkVerbose(network types.NetworkResource, service string, instances uint64) bool {
   215  	if service, ok := network.Services[service]; ok {
   216  		if len(service.Tasks) == int(instances) {
   217  			return true
   218  		}
   219  	}
   220  	return false
   221  }