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 }