github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/integration/internal/swarm/service.go (about)

     1  package swarm
     2  
     3  import (
     4  	"context"
     5  	"runtime"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/docker/docker/api/types"
    10  	"github.com/docker/docker/api/types/filters"
    11  	swarmtypes "github.com/docker/docker/api/types/swarm"
    12  	"github.com/docker/docker/internal/test/daemon"
    13  	"github.com/docker/docker/internal/test/environment"
    14  	"gotest.tools/assert"
    15  	"gotest.tools/poll"
    16  	"gotest.tools/skip"
    17  )
    18  
    19  // ServicePoll tweaks the pollSettings for `service`
    20  func ServicePoll(config *poll.Settings) {
    21  	// Override the default pollSettings for `service` resource here ...
    22  	config.Timeout = 30 * time.Second
    23  	config.Delay = 100 * time.Millisecond
    24  	if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
    25  		config.Timeout = 90 * time.Second
    26  	}
    27  }
    28  
    29  // NetworkPoll tweaks the pollSettings for `network`
    30  func NetworkPoll(config *poll.Settings) {
    31  	// Override the default pollSettings for `network` resource here ...
    32  	config.Timeout = 30 * time.Second
    33  	config.Delay = 100 * time.Millisecond
    34  
    35  	if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
    36  		config.Timeout = 50 * time.Second
    37  	}
    38  }
    39  
    40  // ContainerPoll tweaks the pollSettings for `container`
    41  func ContainerPoll(config *poll.Settings) {
    42  	// Override the default pollSettings for `container` resource here ...
    43  
    44  	if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
    45  		config.Timeout = 30 * time.Second
    46  		config.Delay = 100 * time.Millisecond
    47  	}
    48  }
    49  
    50  // NewSwarm creates a swarm daemon for testing
    51  func NewSwarm(t *testing.T, testEnv *environment.Execution, ops ...func(*daemon.Daemon)) *daemon.Daemon {
    52  	t.Helper()
    53  	skip.If(t, testEnv.IsRemoteDaemon)
    54  	skip.If(t, testEnv.DaemonInfo.OSType == "windows")
    55  	if testEnv.DaemonInfo.ExperimentalBuild {
    56  		ops = append(ops, daemon.WithExperimental)
    57  	}
    58  	d := daemon.New(t, ops...)
    59  	d.StartAndSwarmInit(t)
    60  	return d
    61  }
    62  
    63  // ServiceSpecOpt is used with `CreateService` to pass in service spec modifiers
    64  type ServiceSpecOpt func(*swarmtypes.ServiceSpec)
    65  
    66  // CreateService creates a service on the passed in swarm daemon.
    67  func CreateService(t *testing.T, d *daemon.Daemon, opts ...ServiceSpecOpt) string {
    68  	t.Helper()
    69  	spec := defaultServiceSpec()
    70  	for _, o := range opts {
    71  		o(&spec)
    72  	}
    73  
    74  	client := d.NewClientT(t)
    75  	defer client.Close()
    76  
    77  	resp, err := client.ServiceCreate(context.Background(), spec, types.ServiceCreateOptions{})
    78  	assert.NilError(t, err, "error creating service")
    79  	return resp.ID
    80  }
    81  
    82  func defaultServiceSpec() swarmtypes.ServiceSpec {
    83  	var spec swarmtypes.ServiceSpec
    84  	ServiceWithImage("busybox:latest")(&spec)
    85  	ServiceWithCommand([]string{"/bin/top"})(&spec)
    86  	ServiceWithReplicas(1)(&spec)
    87  	return spec
    88  }
    89  
    90  // ServiceWithInit sets whether the service should use init or not
    91  func ServiceWithInit(b *bool) func(*swarmtypes.ServiceSpec) {
    92  	return func(spec *swarmtypes.ServiceSpec) {
    93  		ensureContainerSpec(spec)
    94  		spec.TaskTemplate.ContainerSpec.Init = b
    95  	}
    96  }
    97  
    98  // ServiceWithImage sets the image to use for the service
    99  func ServiceWithImage(image string) func(*swarmtypes.ServiceSpec) {
   100  	return func(spec *swarmtypes.ServiceSpec) {
   101  		ensureContainerSpec(spec)
   102  		spec.TaskTemplate.ContainerSpec.Image = image
   103  	}
   104  }
   105  
   106  // ServiceWithCommand sets the command to use for the service
   107  func ServiceWithCommand(cmd []string) ServiceSpecOpt {
   108  	return func(spec *swarmtypes.ServiceSpec) {
   109  		ensureContainerSpec(spec)
   110  		spec.TaskTemplate.ContainerSpec.Command = cmd
   111  	}
   112  }
   113  
   114  // ServiceWithConfig adds the config reference to the service
   115  func ServiceWithConfig(configRef *swarmtypes.ConfigReference) ServiceSpecOpt {
   116  	return func(spec *swarmtypes.ServiceSpec) {
   117  		ensureContainerSpec(spec)
   118  		spec.TaskTemplate.ContainerSpec.Configs = append(spec.TaskTemplate.ContainerSpec.Configs, configRef)
   119  	}
   120  }
   121  
   122  // ServiceWithSecret adds the secret reference to the service
   123  func ServiceWithSecret(secretRef *swarmtypes.SecretReference) ServiceSpecOpt {
   124  	return func(spec *swarmtypes.ServiceSpec) {
   125  		ensureContainerSpec(spec)
   126  		spec.TaskTemplate.ContainerSpec.Secrets = append(spec.TaskTemplate.ContainerSpec.Secrets, secretRef)
   127  	}
   128  }
   129  
   130  // ServiceWithReplicas sets the replicas for the service
   131  func ServiceWithReplicas(n uint64) ServiceSpecOpt {
   132  	return func(spec *swarmtypes.ServiceSpec) {
   133  		spec.Mode = swarmtypes.ServiceMode{
   134  			Replicated: &swarmtypes.ReplicatedService{
   135  				Replicas: &n,
   136  			},
   137  		}
   138  	}
   139  }
   140  
   141  // ServiceWithName sets the name of the service
   142  func ServiceWithName(name string) ServiceSpecOpt {
   143  	return func(spec *swarmtypes.ServiceSpec) {
   144  		spec.Annotations.Name = name
   145  	}
   146  }
   147  
   148  // ServiceWithNetwork sets the network of the service
   149  func ServiceWithNetwork(network string) ServiceSpecOpt {
   150  	return func(spec *swarmtypes.ServiceSpec) {
   151  		spec.TaskTemplate.Networks = append(spec.TaskTemplate.Networks,
   152  			swarmtypes.NetworkAttachmentConfig{Target: network})
   153  	}
   154  }
   155  
   156  // ServiceWithEndpoint sets the Endpoint of the service
   157  func ServiceWithEndpoint(endpoint *swarmtypes.EndpointSpec) ServiceSpecOpt {
   158  	return func(spec *swarmtypes.ServiceSpec) {
   159  		spec.EndpointSpec = endpoint
   160  	}
   161  }
   162  
   163  // GetRunningTasks gets the list of running tasks for a service
   164  func GetRunningTasks(t *testing.T, d *daemon.Daemon, serviceID string) []swarmtypes.Task {
   165  	t.Helper()
   166  	client := d.NewClientT(t)
   167  	defer client.Close()
   168  
   169  	filterArgs := filters.NewArgs()
   170  	filterArgs.Add("desired-state", "running")
   171  	filterArgs.Add("service", serviceID)
   172  
   173  	options := types.TaskListOptions{
   174  		Filters: filterArgs,
   175  	}
   176  	tasks, err := client.TaskList(context.Background(), options)
   177  	assert.NilError(t, err)
   178  	return tasks
   179  }
   180  
   181  // ExecTask runs the passed in exec config on the given task
   182  func ExecTask(t *testing.T, d *daemon.Daemon, task swarmtypes.Task, config types.ExecConfig) types.HijackedResponse {
   183  	t.Helper()
   184  	client := d.NewClientT(t)
   185  	defer client.Close()
   186  
   187  	ctx := context.Background()
   188  	resp, err := client.ContainerExecCreate(ctx, task.Status.ContainerStatus.ContainerID, config)
   189  	assert.NilError(t, err, "error creating exec")
   190  
   191  	startCheck := types.ExecStartCheck{}
   192  	attach, err := client.ContainerExecAttach(ctx, resp.ID, startCheck)
   193  	assert.NilError(t, err, "error attaching to exec")
   194  	return attach
   195  }
   196  
   197  func ensureContainerSpec(spec *swarmtypes.ServiceSpec) {
   198  	if spec.TaskTemplate.ContainerSpec == nil {
   199  		spec.TaskTemplate.ContainerSpec = &swarmtypes.ContainerSpec{}
   200  	}
   201  }