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 }