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

     1  package service // import "github.com/docker/docker/integration/service"
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/docker/docker/api/types"
     8  	swarmtypes "github.com/docker/docker/api/types/swarm"
     9  	"github.com/docker/docker/client"
    10  	"github.com/docker/docker/integration/internal/network"
    11  	"github.com/docker/docker/integration/internal/swarm"
    12  	"gotest.tools/assert"
    13  	is "gotest.tools/assert/cmp"
    14  	"gotest.tools/poll"
    15  	"gotest.tools/skip"
    16  )
    17  
    18  func TestServiceUpdateLabel(t *testing.T) {
    19  	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
    20  	defer setupTest(t)()
    21  	d := swarm.NewSwarm(t, testEnv)
    22  	defer d.Stop(t)
    23  	cli := d.NewClientT(t)
    24  	defer cli.Close()
    25  
    26  	ctx := context.Background()
    27  	serviceName := "TestService_" + t.Name()
    28  	serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName))
    29  	service := getService(t, cli, serviceID)
    30  	assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{}))
    31  
    32  	// add label to empty set
    33  	service.Spec.Labels["foo"] = "bar"
    34  	_, err := cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
    35  	assert.NilError(t, err)
    36  	poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll)
    37  	service = getService(t, cli, serviceID)
    38  	assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"}))
    39  
    40  	// add label to non-empty set
    41  	service.Spec.Labels["foo2"] = "bar"
    42  	_, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
    43  	assert.NilError(t, err)
    44  	poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll)
    45  	service = getService(t, cli, serviceID)
    46  	assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar", "foo2": "bar"}))
    47  
    48  	delete(service.Spec.Labels, "foo2")
    49  	_, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
    50  	assert.NilError(t, err)
    51  	poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll)
    52  	service = getService(t, cli, serviceID)
    53  	assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"}))
    54  
    55  	delete(service.Spec.Labels, "foo")
    56  	_, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
    57  	assert.NilError(t, err)
    58  	poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll)
    59  	service = getService(t, cli, serviceID)
    60  	assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{}))
    61  
    62  	// now make sure we can add again
    63  	service.Spec.Labels["foo"] = "bar"
    64  	_, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
    65  	assert.NilError(t, err)
    66  	poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll)
    67  	service = getService(t, cli, serviceID)
    68  	assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"}))
    69  
    70  	err = cli.ServiceRemove(context.Background(), serviceID)
    71  	assert.NilError(t, err)
    72  }
    73  
    74  func TestServiceUpdateSecrets(t *testing.T) {
    75  	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
    76  	defer setupTest(t)()
    77  	d := swarm.NewSwarm(t, testEnv)
    78  	defer d.Stop(t)
    79  	cli := d.NewClientT(t)
    80  	defer cli.Close()
    81  
    82  	ctx := context.Background()
    83  	secretName := "TestSecret_" + t.Name()
    84  	secretTarget := "targetName"
    85  	resp, err := cli.SecretCreate(ctx, swarmtypes.SecretSpec{
    86  		Annotations: swarmtypes.Annotations{
    87  			Name: secretName,
    88  		},
    89  		Data: []byte("TESTINGDATA"),
    90  	})
    91  	assert.NilError(t, err)
    92  	assert.Check(t, resp.ID != "")
    93  
    94  	serviceName := "TestService_" + t.Name()
    95  	serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName))
    96  	service := getService(t, cli, serviceID)
    97  
    98  	// add secret
    99  	service.Spec.TaskTemplate.ContainerSpec.Secrets = append(service.Spec.TaskTemplate.ContainerSpec.Secrets,
   100  		&swarmtypes.SecretReference{
   101  			File: &swarmtypes.SecretReferenceFileTarget{
   102  				Name: secretTarget,
   103  				UID:  "0",
   104  				GID:  "0",
   105  				Mode: 0600,
   106  			},
   107  			SecretID:   resp.ID,
   108  			SecretName: secretName,
   109  		},
   110  	)
   111  	_, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
   112  	assert.NilError(t, err)
   113  	poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
   114  
   115  	service = getService(t, cli, serviceID)
   116  	secrets := service.Spec.TaskTemplate.ContainerSpec.Secrets
   117  	assert.Assert(t, is.Equal(1, len(secrets)))
   118  
   119  	secret := *secrets[0]
   120  	assert.Check(t, is.Equal(secretName, secret.SecretName))
   121  	assert.Check(t, nil != secret.File)
   122  	assert.Check(t, is.Equal(secretTarget, secret.File.Name))
   123  
   124  	// remove
   125  	service.Spec.TaskTemplate.ContainerSpec.Secrets = []*swarmtypes.SecretReference{}
   126  	_, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
   127  	assert.NilError(t, err)
   128  	poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
   129  	service = getService(t, cli, serviceID)
   130  	assert.Check(t, is.Equal(0, len(service.Spec.TaskTemplate.ContainerSpec.Secrets)))
   131  
   132  	err = cli.ServiceRemove(context.Background(), serviceID)
   133  	assert.NilError(t, err)
   134  }
   135  
   136  func TestServiceUpdateConfigs(t *testing.T) {
   137  	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
   138  	defer setupTest(t)()
   139  	d := swarm.NewSwarm(t, testEnv)
   140  	defer d.Stop(t)
   141  	cli := d.NewClientT(t)
   142  	defer cli.Close()
   143  
   144  	ctx := context.Background()
   145  	configName := "TestConfig_" + t.Name()
   146  	configTarget := "targetName"
   147  	resp, err := cli.ConfigCreate(ctx, swarmtypes.ConfigSpec{
   148  		Annotations: swarmtypes.Annotations{
   149  			Name: configName,
   150  		},
   151  		Data: []byte("TESTINGDATA"),
   152  	})
   153  	assert.NilError(t, err)
   154  	assert.Check(t, resp.ID != "")
   155  
   156  	serviceName := "TestService_" + t.Name()
   157  	serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName))
   158  	service := getService(t, cli, serviceID)
   159  
   160  	// add config
   161  	service.Spec.TaskTemplate.ContainerSpec.Configs = append(service.Spec.TaskTemplate.ContainerSpec.Configs,
   162  		&swarmtypes.ConfigReference{
   163  			File: &swarmtypes.ConfigReferenceFileTarget{
   164  				Name: configTarget,
   165  				UID:  "0",
   166  				GID:  "0",
   167  				Mode: 0600,
   168  			},
   169  			ConfigID:   resp.ID,
   170  			ConfigName: configName,
   171  		},
   172  	)
   173  	_, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
   174  	assert.NilError(t, err)
   175  	poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
   176  
   177  	service = getService(t, cli, serviceID)
   178  	configs := service.Spec.TaskTemplate.ContainerSpec.Configs
   179  	assert.Assert(t, is.Equal(1, len(configs)))
   180  
   181  	config := *configs[0]
   182  	assert.Check(t, is.Equal(configName, config.ConfigName))
   183  	assert.Check(t, nil != config.File)
   184  	assert.Check(t, is.Equal(configTarget, config.File.Name))
   185  
   186  	// remove
   187  	service.Spec.TaskTemplate.ContainerSpec.Configs = []*swarmtypes.ConfigReference{}
   188  	_, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
   189  	assert.NilError(t, err)
   190  	poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
   191  	service = getService(t, cli, serviceID)
   192  	assert.Check(t, is.Equal(0, len(service.Spec.TaskTemplate.ContainerSpec.Configs)))
   193  
   194  	err = cli.ServiceRemove(context.Background(), serviceID)
   195  	assert.NilError(t, err)
   196  }
   197  
   198  func TestServiceUpdateNetwork(t *testing.T) {
   199  	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
   200  	defer setupTest(t)()
   201  	d := swarm.NewSwarm(t, testEnv)
   202  	defer d.Stop(t)
   203  	cli := d.NewClientT(t)
   204  	defer cli.Close()
   205  
   206  	ctx := context.Background()
   207  
   208  	// Create a overlay network
   209  	testNet := "testNet" + t.Name()
   210  	overlayID := network.CreateNoError(t, ctx, cli, testNet,
   211  		network.WithDriver("overlay"))
   212  
   213  	var instances uint64 = 1
   214  	// Create service with the overlay network
   215  	serviceName := "TestServiceUpdateNetworkRM_" + t.Name()
   216  	serviceID := swarm.CreateService(t, d,
   217  		swarm.ServiceWithReplicas(instances),
   218  		swarm.ServiceWithName(serviceName),
   219  		swarm.ServiceWithNetwork(testNet))
   220  
   221  	poll.WaitOn(t, swarm.RunningTasksCount(cli, serviceID, instances), swarm.ServicePoll)
   222  	service := getService(t, cli, serviceID)
   223  	netInfo, err := cli.NetworkInspect(ctx, testNet, types.NetworkInspectOptions{
   224  		Verbose: true,
   225  		Scope:   "swarm",
   226  	})
   227  	assert.NilError(t, err)
   228  	assert.Assert(t, len(netInfo.Containers) == 2, "Expected 2 endpoints, one for container and one for LB Sandbox")
   229  
   230  	//Remove network from service
   231  	service.Spec.TaskTemplate.Networks = []swarmtypes.NetworkAttachmentConfig{}
   232  	_, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
   233  	assert.NilError(t, err)
   234  	poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
   235  
   236  	netInfo, err = cli.NetworkInspect(ctx, testNet, types.NetworkInspectOptions{
   237  		Verbose: true,
   238  		Scope:   "swarm",
   239  	})
   240  
   241  	assert.NilError(t, err)
   242  	assert.Assert(t, len(netInfo.Containers) == 0, "Load balancing endpoint still exists in network")
   243  
   244  	err = cli.NetworkRemove(ctx, overlayID)
   245  	assert.NilError(t, err)
   246  
   247  	err = cli.ServiceRemove(ctx, serviceID)
   248  	assert.NilError(t, err)
   249  }
   250  
   251  func getService(t *testing.T, cli client.ServiceAPIClient, serviceID string) swarmtypes.Service {
   252  	t.Helper()
   253  	service, _, err := cli.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
   254  	assert.NilError(t, err)
   255  	return service
   256  }
   257  
   258  func serviceIsUpdated(client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result {
   259  	return func(log poll.LogT) poll.Result {
   260  		service, _, err := client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
   261  		switch {
   262  		case err != nil:
   263  			return poll.Error(err)
   264  		case service.UpdateStatus != nil && service.UpdateStatus.State == swarmtypes.UpdateStateCompleted:
   265  			return poll.Success()
   266  		default:
   267  			if service.UpdateStatus != nil {
   268  				return poll.Continue("waiting for service %s to be updated, state: %s, message: %s", serviceID, service.UpdateStatus.State, service.UpdateStatus.Message)
   269  			}
   270  			return poll.Continue("waiting for service %s to be updated", serviceID)
   271  		}
   272  	}
   273  }
   274  
   275  func serviceSpecIsUpdated(client client.ServiceAPIClient, serviceID string, serviceOldVersion uint64) func(log poll.LogT) poll.Result {
   276  	return func(log poll.LogT) poll.Result {
   277  		service, _, err := client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
   278  		switch {
   279  		case err != nil:
   280  			return poll.Error(err)
   281  		case service.Version.Index > serviceOldVersion:
   282  			return poll.Success()
   283  		default:
   284  			return poll.Continue("waiting for service %s to be updated", serviceID)
   285  		}
   286  	}
   287  }