github.com/ali-iotechsys/cli@v20.10.0+incompatible/cli/command/service/create_test.go (about)

     1  package service
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/docker/docker/api/types"
     8  	"github.com/docker/docker/api/types/swarm"
     9  	"gotest.tools/v3/assert"
    10  	is "gotest.tools/v3/assert/cmp"
    11  
    12  	cliopts "github.com/docker/cli/opts"
    13  )
    14  
    15  // fakeConfigAPIClientList is used to let us pass a closure as a
    16  // ConfigAPIClient, to use as ConfigList. for all the other methods in the
    17  // interface, it does nothing, not even return an error, so don't use them
    18  type fakeConfigAPIClientList func(context.Context, types.ConfigListOptions) ([]swarm.Config, error)
    19  
    20  func (f fakeConfigAPIClientList) ConfigList(ctx context.Context, opts types.ConfigListOptions) ([]swarm.Config, error) {
    21  	return f(ctx, opts)
    22  }
    23  
    24  func (f fakeConfigAPIClientList) ConfigCreate(_ context.Context, _ swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
    25  	return types.ConfigCreateResponse{}, nil
    26  }
    27  
    28  func (f fakeConfigAPIClientList) ConfigRemove(_ context.Context, _ string) error {
    29  	return nil
    30  }
    31  
    32  func (f fakeConfigAPIClientList) ConfigInspectWithRaw(_ context.Context, _ string) (swarm.Config, []byte, error) {
    33  	return swarm.Config{}, nil, nil
    34  }
    35  
    36  func (f fakeConfigAPIClientList) ConfigUpdate(_ context.Context, _ string, _ swarm.Version, _ swarm.ConfigSpec) error {
    37  	return nil
    38  }
    39  
    40  // TestSetConfigsWithCredSpecAndConfigs tests that the setConfigs function for
    41  // create correctly looks up the right configs, and correctly handles the
    42  // credentialSpec
    43  func TestSetConfigsWithCredSpecAndConfigs(t *testing.T) {
    44  	// we can't directly access the internal fields of the ConfigOpt struct, so
    45  	// we need to let it do the parsing
    46  	configOpt := &cliopts.ConfigOpt{}
    47  	configOpt.Set("bar")
    48  	opts := &serviceOptions{
    49  		credentialSpec: credentialSpecOpt{
    50  			value: &swarm.CredentialSpec{
    51  				Config: "foo",
    52  			},
    53  			source: "config://foo",
    54  		},
    55  		configs: *configOpt,
    56  	}
    57  
    58  	// create a service spec. we need to be sure to fill in the nullable
    59  	// fields, like the code expects
    60  	service := &swarm.ServiceSpec{
    61  		TaskTemplate: swarm.TaskSpec{
    62  			ContainerSpec: &swarm.ContainerSpec{
    63  				Privileges: &swarm.Privileges{
    64  					CredentialSpec: opts.credentialSpec.value,
    65  				},
    66  			},
    67  		},
    68  	}
    69  
    70  	// set up a function to use as the list function
    71  	var fakeClient fakeConfigAPIClientList = func(_ context.Context, opts types.ConfigListOptions) ([]swarm.Config, error) {
    72  		f := opts.Filters
    73  
    74  		// we're expecting the filter to have names "foo" and "bar"
    75  		names := f.Get("name")
    76  		assert.Equal(t, len(names), 2)
    77  		assert.Assert(t, is.Contains(names, "foo"))
    78  		assert.Assert(t, is.Contains(names, "bar"))
    79  
    80  		return []swarm.Config{
    81  			{
    82  				ID: "fooID",
    83  				Spec: swarm.ConfigSpec{
    84  					Annotations: swarm.Annotations{
    85  						Name: "foo",
    86  					},
    87  				},
    88  			}, {
    89  				ID: "barID",
    90  				Spec: swarm.ConfigSpec{
    91  					Annotations: swarm.Annotations{
    92  						Name: "bar",
    93  					},
    94  				},
    95  			},
    96  		}, nil
    97  	}
    98  
    99  	// now call setConfigs
   100  	err := setConfigs(fakeClient, service, opts)
   101  	// verify no error is returned
   102  	assert.NilError(t, err)
   103  
   104  	credSpecConfigValue := service.TaskTemplate.ContainerSpec.Privileges.CredentialSpec.Config
   105  	assert.Equal(t, credSpecConfigValue, "fooID")
   106  
   107  	configRefs := service.TaskTemplate.ContainerSpec.Configs
   108  	assert.Assert(t, is.Contains(configRefs, &swarm.ConfigReference{
   109  		ConfigID:   "fooID",
   110  		ConfigName: "foo",
   111  		Runtime:    &swarm.ConfigReferenceRuntimeTarget{},
   112  	}), "expected configRefs to contain foo config")
   113  	assert.Assert(t, is.Contains(configRefs, &swarm.ConfigReference{
   114  		ConfigID:   "barID",
   115  		ConfigName: "bar",
   116  		File: &swarm.ConfigReferenceFileTarget{
   117  			Name: "bar",
   118  			// these are the default field values
   119  			UID:  "0",
   120  			GID:  "0",
   121  			Mode: 0444,
   122  		},
   123  	}), "expected configRefs to contain bar config")
   124  }
   125  
   126  // TestSetConfigsOnlyCredSpec tests that even if a CredentialSpec is the only
   127  // config needed, setConfigs still works
   128  func TestSetConfigsOnlyCredSpec(t *testing.T) {
   129  	opts := &serviceOptions{
   130  		credentialSpec: credentialSpecOpt{
   131  			value: &swarm.CredentialSpec{
   132  				Config: "foo",
   133  			},
   134  			source: "config://foo",
   135  		},
   136  	}
   137  
   138  	service := &swarm.ServiceSpec{
   139  		TaskTemplate: swarm.TaskSpec{
   140  			ContainerSpec: &swarm.ContainerSpec{
   141  				Privileges: &swarm.Privileges{
   142  					CredentialSpec: opts.credentialSpec.value,
   143  				},
   144  			},
   145  		},
   146  	}
   147  
   148  	// set up a function to use as the list function
   149  	var fakeClient fakeConfigAPIClientList = func(_ context.Context, opts types.ConfigListOptions) ([]swarm.Config, error) {
   150  		f := opts.Filters
   151  
   152  		names := f.Get("name")
   153  		assert.Equal(t, len(names), 1)
   154  		assert.Assert(t, is.Contains(names, "foo"))
   155  
   156  		return []swarm.Config{
   157  			{
   158  				ID: "fooID",
   159  				Spec: swarm.ConfigSpec{
   160  					Annotations: swarm.Annotations{
   161  						Name: "foo",
   162  					},
   163  				},
   164  			},
   165  		}, nil
   166  	}
   167  
   168  	// now call setConfigs
   169  	err := setConfigs(fakeClient, service, opts)
   170  	// verify no error is returned
   171  	assert.NilError(t, err)
   172  
   173  	credSpecConfigValue := service.TaskTemplate.ContainerSpec.Privileges.CredentialSpec.Config
   174  	assert.Equal(t, credSpecConfigValue, "fooID")
   175  
   176  	configRefs := service.TaskTemplate.ContainerSpec.Configs
   177  	assert.Assert(t, is.Contains(configRefs, &swarm.ConfigReference{
   178  		ConfigID:   "fooID",
   179  		ConfigName: "foo",
   180  		Runtime:    &swarm.ConfigReferenceRuntimeTarget{},
   181  	}))
   182  }
   183  
   184  // TestSetConfigsOnlyConfigs verifies setConfigs when only configs (and not a
   185  // CredentialSpec) is needed.
   186  func TestSetConfigsOnlyConfigs(t *testing.T) {
   187  	configOpt := &cliopts.ConfigOpt{}
   188  	configOpt.Set("bar")
   189  	opts := &serviceOptions{
   190  		configs: *configOpt,
   191  	}
   192  
   193  	service := &swarm.ServiceSpec{
   194  		TaskTemplate: swarm.TaskSpec{
   195  			ContainerSpec: &swarm.ContainerSpec{},
   196  		},
   197  	}
   198  
   199  	var fakeClient fakeConfigAPIClientList = func(_ context.Context, opts types.ConfigListOptions) ([]swarm.Config, error) {
   200  		f := opts.Filters
   201  
   202  		names := f.Get("name")
   203  		assert.Equal(t, len(names), 1)
   204  		assert.Assert(t, is.Contains(names, "bar"))
   205  
   206  		return []swarm.Config{
   207  			{
   208  				ID: "barID",
   209  				Spec: swarm.ConfigSpec{
   210  					Annotations: swarm.Annotations{
   211  						Name: "bar",
   212  					},
   213  				},
   214  			},
   215  		}, nil
   216  	}
   217  
   218  	// now call setConfigs
   219  	err := setConfigs(fakeClient, service, opts)
   220  	// verify no error is returned
   221  	assert.NilError(t, err)
   222  
   223  	configRefs := service.TaskTemplate.ContainerSpec.Configs
   224  	assert.Assert(t, is.Contains(configRefs, &swarm.ConfigReference{
   225  		ConfigID:   "barID",
   226  		ConfigName: "bar",
   227  		File: &swarm.ConfigReferenceFileTarget{
   228  			Name: "bar",
   229  			// these are the default field values
   230  			UID:  "0",
   231  			GID:  "0",
   232  			Mode: 0444,
   233  		},
   234  	}))
   235  }
   236  
   237  // TestSetConfigsNoConfigs checks that setConfigs works when there are no
   238  // configs of any kind needed
   239  func TestSetConfigsNoConfigs(t *testing.T) {
   240  	// add a credentialSpec that isn't a config
   241  	opts := &serviceOptions{
   242  		credentialSpec: credentialSpecOpt{
   243  			value: &swarm.CredentialSpec{
   244  				File: "foo",
   245  			},
   246  			source: "file://foo",
   247  		},
   248  	}
   249  	service := &swarm.ServiceSpec{
   250  		TaskTemplate: swarm.TaskSpec{
   251  			ContainerSpec: &swarm.ContainerSpec{
   252  				Privileges: &swarm.Privileges{
   253  					CredentialSpec: opts.credentialSpec.value,
   254  				},
   255  			},
   256  		},
   257  	}
   258  
   259  	var fakeClient fakeConfigAPIClientList = func(_ context.Context, opts types.ConfigListOptions) ([]swarm.Config, error) {
   260  		// assert false -- we should never call this function
   261  		assert.Assert(t, false, "we should not be listing configs")
   262  		return nil, nil
   263  	}
   264  
   265  	err := setConfigs(fakeClient, service, opts)
   266  	assert.NilError(t, err)
   267  
   268  	// ensure that the value of the credentialspec has not changed
   269  	assert.Equal(t, service.TaskTemplate.ContainerSpec.Privileges.CredentialSpec.File, "foo")
   270  	assert.Equal(t, service.TaskTemplate.ContainerSpec.Privileges.CredentialSpec.Config, "")
   271  }