github.com/sams1990/dockerrepo@v17.12.1-ce-rc2+incompatible/integration/service/create_test.go (about)

     1  package service
     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/docker/docker/integration-cli/request"
    13  	"github.com/gotestyourself/gotestyourself/poll"
    14  	"github.com/stretchr/testify/require"
    15  	"golang.org/x/net/context"
    16  )
    17  
    18  func TestCreateServiceMultipleTimes(t *testing.T) {
    19  	defer setupTest(t)()
    20  	d := newSwarm(t)
    21  	defer d.Stop(t)
    22  	client, err := request.NewClientForHost(d.Sock())
    23  	require.NoError(t, err)
    24  
    25  	overlayName := "overlay1"
    26  	networkCreate := types.NetworkCreate{
    27  		CheckDuplicate: true,
    28  		Driver:         "overlay",
    29  	}
    30  
    31  	netResp, err := client.NetworkCreate(context.Background(), overlayName, networkCreate)
    32  	require.NoError(t, err)
    33  	overlayID := netResp.ID
    34  
    35  	var instances uint64 = 4
    36  	serviceSpec := swarmServiceSpec("TestService", instances)
    37  	serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: overlayName})
    38  
    39  	serviceResp, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
    40  		QueryRegistry: false,
    41  	})
    42  	require.NoError(t, err)
    43  
    44  	pollSettings := func(config *poll.Settings) {
    45  		if runtime.GOARCH == "arm" {
    46  			config.Timeout = 30 * time.Second
    47  			config.Delay = 100 * time.Millisecond
    48  		}
    49  	}
    50  
    51  	serviceID := serviceResp.ID
    52  	poll.WaitOn(t, serviceRunningTasksCount(client, serviceID, instances), pollSettings)
    53  
    54  	_, _, err = client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
    55  	require.NoError(t, err)
    56  
    57  	err = client.ServiceRemove(context.Background(), serviceID)
    58  	require.NoError(t, err)
    59  
    60  	poll.WaitOn(t, serviceIsRemoved(client, serviceID), pollSettings)
    61  	poll.WaitOn(t, noTasks(client), pollSettings)
    62  
    63  	serviceResp, err = client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
    64  		QueryRegistry: false,
    65  	})
    66  	require.NoError(t, err)
    67  
    68  	serviceID2 := serviceResp.ID
    69  	poll.WaitOn(t, serviceRunningTasksCount(client, serviceID2, instances), pollSettings)
    70  
    71  	err = client.ServiceRemove(context.Background(), serviceID2)
    72  	require.NoError(t, err)
    73  
    74  	poll.WaitOn(t, serviceIsRemoved(client, serviceID2), pollSettings)
    75  	poll.WaitOn(t, noTasks(client), pollSettings)
    76  
    77  	err = client.NetworkRemove(context.Background(), overlayID)
    78  	require.NoError(t, err)
    79  
    80  	poll.WaitOn(t, networkIsRemoved(client, overlayID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
    81  }
    82  
    83  func swarmServiceSpec(name string, replicas uint64) swarm.ServiceSpec {
    84  	return swarm.ServiceSpec{
    85  		Annotations: swarm.Annotations{
    86  			Name: name,
    87  		},
    88  		TaskTemplate: swarm.TaskSpec{
    89  			ContainerSpec: &swarm.ContainerSpec{
    90  				Image:   "busybox:latest",
    91  				Command: []string{"/bin/top"},
    92  			},
    93  		},
    94  		Mode: swarm.ServiceMode{
    95  			Replicated: &swarm.ReplicatedService{
    96  				Replicas: &replicas,
    97  			},
    98  		},
    99  	}
   100  }
   101  
   102  func serviceRunningTasksCount(client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result {
   103  	return func(log poll.LogT) poll.Result {
   104  		filter := filters.NewArgs()
   105  		filter.Add("service", serviceID)
   106  		tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
   107  			Filters: filter,
   108  		})
   109  		switch {
   110  		case err != nil:
   111  			return poll.Error(err)
   112  		case len(tasks) == int(instances):
   113  			for _, task := range tasks {
   114  				if task.Status.State != swarm.TaskStateRunning {
   115  					return poll.Continue("waiting for tasks to enter run state")
   116  				}
   117  			}
   118  			return poll.Success()
   119  		default:
   120  			return poll.Continue("task count at %d waiting for %d", len(tasks), instances)
   121  		}
   122  	}
   123  }
   124  
   125  func noTasks(client client.ServiceAPIClient) func(log poll.LogT) poll.Result {
   126  	return func(log poll.LogT) poll.Result {
   127  		filter := filters.NewArgs()
   128  		tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
   129  			Filters: filter,
   130  		})
   131  		switch {
   132  		case err != nil:
   133  			return poll.Error(err)
   134  		case len(tasks) == 0:
   135  			return poll.Success()
   136  		default:
   137  			return poll.Continue("task count at %d waiting for 0", len(tasks))
   138  		}
   139  	}
   140  }
   141  
   142  func serviceIsRemoved(client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result {
   143  	return func(log poll.LogT) poll.Result {
   144  		filter := filters.NewArgs()
   145  		filter.Add("service", serviceID)
   146  		_, err := client.TaskList(context.Background(), types.TaskListOptions{
   147  			Filters: filter,
   148  		})
   149  		if err == nil {
   150  			return poll.Continue("waiting for service %s to be deleted", serviceID)
   151  		}
   152  		return poll.Success()
   153  	}
   154  }
   155  
   156  func networkIsRemoved(client client.NetworkAPIClient, networkID string) func(log poll.LogT) poll.Result {
   157  	return func(log poll.LogT) poll.Result {
   158  		_, err := client.NetworkInspect(context.Background(), networkID, types.NetworkInspectOptions{})
   159  		if err == nil {
   160  			return poll.Continue("waiting for network %s to be removed", networkID)
   161  		}
   162  		return poll.Success()
   163  	}
   164  }