github.com/rumpl/bof@v23.0.0-rc.2+incompatible/integration/config/config_test.go (about) 1 package config // import "github.com/docker/docker/integration/config" 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "sort" 8 "testing" 9 "time" 10 11 "github.com/docker/docker/api/types" 12 "github.com/docker/docker/api/types/filters" 13 swarmtypes "github.com/docker/docker/api/types/swarm" 14 "github.com/docker/docker/client" 15 "github.com/docker/docker/errdefs" 16 "github.com/docker/docker/integration/internal/swarm" 17 "github.com/docker/docker/pkg/stdcopy" 18 "gotest.tools/v3/assert" 19 is "gotest.tools/v3/assert/cmp" 20 "gotest.tools/v3/poll" 21 "gotest.tools/v3/skip" 22 ) 23 24 func TestConfigInspect(t *testing.T) { 25 skip.If(t, testEnv.DaemonInfo.OSType == "windows") 26 27 defer setupTest(t)() 28 d := swarm.NewSwarm(t, testEnv) 29 defer d.Stop(t) 30 c := d.NewClientT(t) 31 defer c.Close() 32 33 ctx := context.Background() 34 35 testName := t.Name() 36 configID := createConfig(ctx, t, c, testName, []byte("TESTINGDATA"), nil) 37 38 insp, body, err := c.ConfigInspectWithRaw(ctx, configID) 39 assert.NilError(t, err) 40 assert.Check(t, is.Equal(insp.Spec.Name, testName)) 41 42 var config swarmtypes.Config 43 err = json.Unmarshal(body, &config) 44 assert.NilError(t, err) 45 assert.Check(t, is.DeepEqual(config, insp)) 46 } 47 48 func TestConfigList(t *testing.T) { 49 skip.If(t, testEnv.DaemonInfo.OSType == "windows") 50 51 defer setupTest(t)() 52 d := swarm.NewSwarm(t, testEnv) 53 defer d.Stop(t) 54 c := d.NewClientT(t) 55 defer c.Close() 56 ctx := context.Background() 57 58 // This test case is ported from the original TestConfigsEmptyList 59 configs, err := c.ConfigList(ctx, types.ConfigListOptions{}) 60 assert.NilError(t, err) 61 assert.Check(t, is.Equal(len(configs), 0)) 62 63 testName0 := "test0-" + t.Name() 64 testName1 := "test1-" + t.Name() 65 testNames := []string{testName0, testName1} 66 sort.Strings(testNames) 67 68 // create config test0 69 createConfig(ctx, t, c, testName0, []byte("TESTINGDATA0"), map[string]string{"type": "test"}) 70 71 config1ID := createConfig(ctx, t, c, testName1, []byte("TESTINGDATA1"), map[string]string{"type": "production"}) 72 73 // test by `config ls` 74 entries, err := c.ConfigList(ctx, types.ConfigListOptions{}) 75 assert.NilError(t, err) 76 assert.Check(t, is.DeepEqual(configNamesFromList(entries), testNames)) 77 78 testCases := []struct { 79 filters filters.Args 80 expected []string 81 }{ 82 // test filter by name `config ls --filter name=xxx` 83 { 84 filters: filters.NewArgs(filters.Arg("name", testName0)), 85 expected: []string{testName0}, 86 }, 87 // test filter by id `config ls --filter id=xxx` 88 { 89 filters: filters.NewArgs(filters.Arg("id", config1ID)), 90 expected: []string{testName1}, 91 }, 92 // test filter by label `config ls --filter label=xxx` 93 { 94 filters: filters.NewArgs(filters.Arg("label", "type")), 95 expected: testNames, 96 }, 97 { 98 filters: filters.NewArgs(filters.Arg("label", "type=test")), 99 expected: []string{testName0}, 100 }, 101 { 102 filters: filters.NewArgs(filters.Arg("label", "type=production")), 103 expected: []string{testName1}, 104 }, 105 } 106 for _, tc := range testCases { 107 entries, err = c.ConfigList(ctx, types.ConfigListOptions{ 108 Filters: tc.filters, 109 }) 110 assert.NilError(t, err) 111 assert.Check(t, is.DeepEqual(configNamesFromList(entries), tc.expected)) 112 } 113 } 114 115 func createConfig(ctx context.Context, t *testing.T, client client.APIClient, name string, data []byte, labels map[string]string) string { 116 config, err := client.ConfigCreate(ctx, swarmtypes.ConfigSpec{ 117 Annotations: swarmtypes.Annotations{ 118 Name: name, 119 Labels: labels, 120 }, 121 Data: data, 122 }) 123 assert.NilError(t, err) 124 assert.Check(t, config.ID != "") 125 return config.ID 126 } 127 128 func TestConfigsCreateAndDelete(t *testing.T) { 129 skip.If(t, testEnv.DaemonInfo.OSType == "windows") 130 131 defer setupTest(t)() 132 d := swarm.NewSwarm(t, testEnv) 133 defer d.Stop(t) 134 c := d.NewClientT(t) 135 defer c.Close() 136 ctx := context.Background() 137 138 testName := "test_config-" + t.Name() 139 configID := createConfig(ctx, t, c, testName, []byte("TESTINGDATA"), nil) 140 141 err := c.ConfigRemove(ctx, configID) 142 assert.NilError(t, err) 143 144 _, _, err = c.ConfigInspectWithRaw(ctx, configID) 145 assert.Check(t, errdefs.IsNotFound(err)) 146 assert.Check(t, is.ErrorContains(err, configID)) 147 148 err = c.ConfigRemove(ctx, "non-existing") 149 assert.Check(t, errdefs.IsNotFound(err)) 150 assert.Check(t, is.ErrorContains(err, "non-existing")) 151 152 testName = "test_secret_with_labels_" + t.Name() 153 configID = createConfig(ctx, t, c, testName, []byte("TESTINGDATA"), map[string]string{ 154 "key1": "value1", 155 "key2": "value2", 156 }) 157 158 insp, _, err := c.ConfigInspectWithRaw(ctx, configID) 159 assert.NilError(t, err) 160 assert.Check(t, is.Equal(insp.Spec.Name, testName)) 161 assert.Check(t, is.Equal(len(insp.Spec.Labels), 2)) 162 assert.Check(t, is.Equal(insp.Spec.Labels["key1"], "value1")) 163 assert.Check(t, is.Equal(insp.Spec.Labels["key2"], "value2")) 164 } 165 166 func TestConfigsUpdate(t *testing.T) { 167 skip.If(t, testEnv.DaemonInfo.OSType == "windows") 168 169 defer setupTest(t)() 170 d := swarm.NewSwarm(t, testEnv) 171 defer d.Stop(t) 172 c := d.NewClientT(t) 173 defer c.Close() 174 ctx := context.Background() 175 176 testName := "test_config-" + t.Name() 177 configID := createConfig(ctx, t, c, testName, []byte("TESTINGDATA"), nil) 178 179 insp, _, err := c.ConfigInspectWithRaw(ctx, configID) 180 assert.NilError(t, err) 181 assert.Check(t, is.Equal(insp.ID, configID)) 182 183 // test UpdateConfig with full ID 184 insp.Spec.Labels = map[string]string{"test": "test1"} 185 err = c.ConfigUpdate(ctx, configID, insp.Version, insp.Spec) 186 assert.NilError(t, err) 187 188 insp, _, err = c.ConfigInspectWithRaw(ctx, configID) 189 assert.NilError(t, err) 190 assert.Check(t, is.Equal(insp.Spec.Labels["test"], "test1")) 191 192 // test UpdateConfig with full name 193 insp.Spec.Labels = map[string]string{"test": "test2"} 194 err = c.ConfigUpdate(ctx, testName, insp.Version, insp.Spec) 195 assert.NilError(t, err) 196 197 insp, _, err = c.ConfigInspectWithRaw(ctx, configID) 198 assert.NilError(t, err) 199 assert.Check(t, is.Equal(insp.Spec.Labels["test"], "test2")) 200 201 // test UpdateConfig with prefix ID 202 insp.Spec.Labels = map[string]string{"test": "test3"} 203 err = c.ConfigUpdate(ctx, configID[:1], insp.Version, insp.Spec) 204 assert.NilError(t, err) 205 206 insp, _, err = c.ConfigInspectWithRaw(ctx, configID) 207 assert.NilError(t, err) 208 assert.Check(t, is.Equal(insp.Spec.Labels["test"], "test3")) 209 210 // test UpdateConfig in updating Data which is not supported in daemon 211 // this test will produce an error in func UpdateConfig 212 insp.Spec.Data = []byte("TESTINGDATA2") 213 err = c.ConfigUpdate(ctx, configID, insp.Version, insp.Spec) 214 assert.Check(t, errdefs.IsInvalidParameter(err)) 215 assert.Check(t, is.ErrorContains(err, "only updates to Labels are allowed")) 216 } 217 218 func TestTemplatedConfig(t *testing.T) { 219 skip.If(t, testEnv.DaemonInfo.OSType == "windows") 220 d := swarm.NewSwarm(t, testEnv) 221 defer d.Stop(t) 222 c := d.NewClientT(t) 223 defer c.Close() 224 ctx := context.Background() 225 226 referencedSecretName := "referencedsecret-" + t.Name() 227 referencedSecretSpec := swarmtypes.SecretSpec{ 228 Annotations: swarmtypes.Annotations{ 229 Name: referencedSecretName, 230 }, 231 Data: []byte("this is a secret"), 232 } 233 referencedSecret, err := c.SecretCreate(ctx, referencedSecretSpec) 234 assert.Check(t, err) 235 236 referencedConfigName := "referencedconfig-" + t.Name() 237 referencedConfigSpec := swarmtypes.ConfigSpec{ 238 Annotations: swarmtypes.Annotations{ 239 Name: referencedConfigName, 240 }, 241 Data: []byte("this is a config"), 242 } 243 referencedConfig, err := c.ConfigCreate(ctx, referencedConfigSpec) 244 assert.Check(t, err) 245 246 templatedConfigName := "templated_config-" + t.Name() 247 configSpec := swarmtypes.ConfigSpec{ 248 Annotations: swarmtypes.Annotations{ 249 Name: templatedConfigName, 250 }, 251 Templating: &swarmtypes.Driver{ 252 Name: "golang", 253 }, 254 Data: []byte("SERVICE_NAME={{.Service.Name}}\n" + 255 "{{secret \"referencedsecrettarget\"}}\n" + 256 "{{config \"referencedconfigtarget\"}}\n"), 257 } 258 259 templatedConfig, err := c.ConfigCreate(ctx, configSpec) 260 assert.Check(t, err) 261 262 serviceName := "svc_" + t.Name() 263 serviceID := swarm.CreateService(t, d, 264 swarm.ServiceWithConfig( 265 &swarmtypes.ConfigReference{ 266 File: &swarmtypes.ConfigReferenceFileTarget{ 267 Name: "templated_config", 268 UID: "0", 269 GID: "0", 270 Mode: 0600, 271 }, 272 ConfigID: templatedConfig.ID, 273 ConfigName: templatedConfigName, 274 }, 275 ), 276 swarm.ServiceWithConfig( 277 &swarmtypes.ConfigReference{ 278 File: &swarmtypes.ConfigReferenceFileTarget{ 279 Name: "referencedconfigtarget", 280 UID: "0", 281 GID: "0", 282 Mode: 0600, 283 }, 284 ConfigID: referencedConfig.ID, 285 ConfigName: referencedConfigName, 286 }, 287 ), 288 swarm.ServiceWithSecret( 289 &swarmtypes.SecretReference{ 290 File: &swarmtypes.SecretReferenceFileTarget{ 291 Name: "referencedsecrettarget", 292 UID: "0", 293 GID: "0", 294 Mode: 0600, 295 }, 296 SecretID: referencedSecret.ID, 297 SecretName: referencedSecretName, 298 }, 299 ), 300 swarm.ServiceWithName(serviceName), 301 ) 302 303 poll.WaitOn(t, swarm.RunningTasksCount(c, serviceID, 1), swarm.ServicePoll, poll.WithTimeout(1*time.Minute)) 304 305 tasks := swarm.GetRunningTasks(t, c, serviceID) 306 assert.Assert(t, len(tasks) > 0, "no running tasks found for service %s", serviceID) 307 308 attach := swarm.ExecTask(t, d, tasks[0], types.ExecConfig{ 309 Cmd: []string{"/bin/cat", "/templated_config"}, 310 AttachStdout: true, 311 AttachStderr: true, 312 }) 313 314 expect := "SERVICE_NAME=" + serviceName + "\n" + 315 "this is a secret\n" + 316 "this is a config\n" 317 assertAttachedStream(t, attach, expect) 318 319 attach = swarm.ExecTask(t, d, tasks[0], types.ExecConfig{ 320 Cmd: []string{"mount"}, 321 AttachStdout: true, 322 AttachStderr: true, 323 }) 324 assertAttachedStream(t, attach, "tmpfs on /templated_config type tmpfs") 325 } 326 327 // Test case for 28884 328 func TestConfigCreateResolve(t *testing.T) { 329 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 330 331 defer setupTest(t)() 332 d := swarm.NewSwarm(t, testEnv) 333 defer d.Stop(t) 334 c := d.NewClientT(t) 335 defer c.Close() 336 337 ctx := context.Background() 338 339 configName := "test_config_" + t.Name() 340 configID := createConfig(ctx, t, c, configName, []byte("foo"), nil) 341 342 fakeName := configID 343 fakeID := createConfig(ctx, t, c, fakeName, []byte("fake foo"), nil) 344 345 entries, err := c.ConfigList(ctx, types.ConfigListOptions{}) 346 assert.NilError(t, err) 347 assert.Assert(t, is.Contains(configNamesFromList(entries), configName)) 348 assert.Assert(t, is.Contains(configNamesFromList(entries), fakeName)) 349 350 err = c.ConfigRemove(ctx, configID) 351 assert.NilError(t, err) 352 353 // Fake one will remain 354 entries, err = c.ConfigList(ctx, types.ConfigListOptions{}) 355 assert.NilError(t, err) 356 assert.Assert(t, is.DeepEqual(configNamesFromList(entries), []string{fakeName})) 357 358 // Remove based on name prefix of the fake one 359 // (which is the same as the ID of foo one) should not work 360 // as search is only done based on: 361 // - Full ID 362 // - Full Name 363 // - Partial ID (prefix) 364 err = c.ConfigRemove(ctx, configID[:5]) 365 assert.Assert(t, nil != err) 366 entries, err = c.ConfigList(ctx, types.ConfigListOptions{}) 367 assert.NilError(t, err) 368 assert.Assert(t, is.DeepEqual(configNamesFromList(entries), []string{fakeName})) 369 370 // Remove based on ID prefix of the fake one should succeed 371 err = c.ConfigRemove(ctx, fakeID[:5]) 372 assert.NilError(t, err) 373 entries, err = c.ConfigList(ctx, types.ConfigListOptions{}) 374 assert.NilError(t, err) 375 assert.Assert(t, is.Equal(0, len(entries))) 376 } 377 378 func assertAttachedStream(t *testing.T, attach types.HijackedResponse, expect string) { 379 buf := bytes.NewBuffer(nil) 380 _, err := stdcopy.StdCopy(buf, buf, attach.Reader) 381 assert.NilError(t, err) 382 assert.Check(t, is.Contains(buf.String(), expect)) 383 } 384 385 func configNamesFromList(entries []swarmtypes.Config) []string { 386 var values []string 387 for _, entry := range entries { 388 values = append(values, entry.Spec.Name) 389 } 390 sort.Strings(values) 391 return values 392 }