github.com/kaisenlinux/docker@v0.0.0-20230510090727-ea55db55fac7/swarmkit/template/getter_test.go (about) 1 package template 2 3 import ( 4 "testing" 5 6 "github.com/docker/swarmkit/agent" 7 "github.com/docker/swarmkit/api" 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestTemplatedSecret(t *testing.T) { 13 templatedSecret := &api.Secret{ 14 ID: "templatedsecret", 15 } 16 17 referencedSecret := &api.Secret{ 18 ID: "referencedsecret", 19 Spec: api.SecretSpec{ 20 Data: []byte("mysecret"), 21 }, 22 } 23 referencedConfig := &api.Config{ 24 ID: "referencedconfig", 25 Spec: api.ConfigSpec{ 26 Data: []byte("myconfig"), 27 }, 28 } 29 30 type testCase struct { 31 desc string 32 secretSpec api.SecretSpec 33 task *api.Task 34 node *api.NodeDescription 35 expected string 36 expectedErr string 37 } 38 39 testCases := []testCase{ 40 { 41 desc: "Test expansion of task context", 42 secretSpec: api.SecretSpec{ 43 Data: []byte("SERVICE_ID={{.Service.ID}}\n" + 44 "SERVICE_NAME={{.Service.Name}}\n" + 45 "TASK_ID={{.Task.ID}}\n" + 46 "TASK_NAME={{.Task.Name}}\n" + 47 "NODE_ID={{.Node.ID}}\n" + 48 "NODE_HOSTNAME={{.Node.Hostname}}\n" + 49 "NODE_OS={{.Node.Platform.OS}}\n" + 50 "NODE_ARCHITECTURE={{.Node.Platform.Architecture}}"), 51 Templating: &api.Driver{Name: "golang"}, 52 }, 53 expected: "SERVICE_ID=serviceID\n" + 54 "SERVICE_NAME=serviceName\n" + 55 "TASK_ID=taskID\n" + 56 "TASK_NAME=serviceName.10.taskID\n" + 57 "NODE_ID=nodeID\n" + 58 "NODE_HOSTNAME=myhostname\n" + 59 "NODE_OS=testOS\n" + 60 "NODE_ARCHITECTURE=testArchitecture", 61 task: modifyTask(func(t *api.Task) { 62 t.Spec = api.TaskSpec{ 63 Runtime: &api.TaskSpec_Container{ 64 Container: &api.ContainerSpec{ 65 Secrets: []*api.SecretReference{ 66 { 67 SecretID: "templatedsecret", 68 SecretName: "templatedsecretname", 69 }, 70 }, 71 }, 72 }, 73 } 74 }), 75 node: modifyNode(func(n *api.NodeDescription) { 76 n.Hostname = "myhostname" 77 n.Platform.OS = "testOS" 78 n.Platform.Architecture = "testArchitecture" 79 }), 80 }, 81 { 82 desc: "Test expansion of secret, by target", 83 secretSpec: api.SecretSpec{ 84 Data: []byte("SECRET_VAL={{secret \"referencedsecrettarget\"}}\n"), 85 Templating: &api.Driver{Name: "golang"}, 86 }, 87 expected: "SECRET_VAL=mysecret\n", 88 task: modifyTask(func(t *api.Task) { 89 t.Spec = api.TaskSpec{ 90 Runtime: &api.TaskSpec_Container{ 91 Container: &api.ContainerSpec{ 92 Secrets: []*api.SecretReference{ 93 { 94 SecretID: "templatedsecret", 95 SecretName: "templatedsecretname", 96 }, 97 { 98 SecretID: "referencedsecret", 99 SecretName: "referencedsecretname", 100 Target: &api.SecretReference_File{ 101 File: &api.FileTarget{ 102 Name: "referencedsecrettarget", 103 UID: "0", 104 GID: "0", 105 Mode: 0666, 106 }, 107 }, 108 }, 109 }, 110 }, 111 }, 112 } 113 }), 114 node: modifyNode(func(n *api.NodeDescription) { 115 // use default values 116 }), 117 }, 118 { 119 desc: "Test expansion of config, by target", 120 secretSpec: api.SecretSpec{ 121 Data: []byte("CONFIG_VAL={{config \"referencedconfigtarget\"}}\n"), 122 Templating: &api.Driver{Name: "golang"}, 123 }, 124 expected: "CONFIG_VAL=myconfig\n", 125 task: modifyTask(func(t *api.Task) { 126 t.Spec = api.TaskSpec{ 127 Runtime: &api.TaskSpec_Container{ 128 Container: &api.ContainerSpec{ 129 Secrets: []*api.SecretReference{ 130 { 131 SecretID: "templatedsecret", 132 SecretName: "templatedsecretname", 133 }, 134 }, 135 Configs: []*api.ConfigReference{ 136 { 137 ConfigID: "referencedconfig", 138 ConfigName: "referencedconfigname", 139 Target: &api.ConfigReference_File{ 140 File: &api.FileTarget{ 141 Name: "referencedconfigtarget", 142 UID: "0", 143 GID: "0", 144 Mode: 0666, 145 }, 146 }, 147 }, 148 }, 149 }, 150 }, 151 } 152 }), 153 node: modifyNode(func(n *api.NodeDescription) { 154 // use default values 155 }), 156 }, 157 { 158 desc: "Test expansion of secret not available to task", 159 secretSpec: api.SecretSpec{ 160 Data: []byte("SECRET_VAL={{secret \"unknowntarget\"}}\n"), 161 Templating: &api.Driver{Name: "golang"}, 162 }, 163 expectedErr: `failed to expand templated secret templatedsecret: template: expansion:1:13: executing "expansion" at <secret "unknowntarget">: error calling secret: secret target unknowntarget not found`, 164 task: modifyTask(func(t *api.Task) { 165 t.Spec = api.TaskSpec{ 166 Runtime: &api.TaskSpec_Container{ 167 Container: &api.ContainerSpec{ 168 Secrets: []*api.SecretReference{ 169 { 170 SecretID: "templatedsecret", 171 SecretName: "templatedsecretname", 172 }, 173 }, 174 }, 175 }, 176 } 177 }), 178 node: modifyNode(func(n *api.NodeDescription) { 179 // use default values 180 }), 181 }, 182 { 183 desc: "Test expansion of config not available to task", 184 secretSpec: api.SecretSpec{ 185 Data: []byte("CONFIG_VAL={{config \"unknowntarget\"}}\n"), 186 Templating: &api.Driver{Name: "golang"}, 187 }, 188 expectedErr: `failed to expand templated secret templatedsecret: template: expansion:1:13: executing "expansion" at <config "unknowntarget">: error calling config: config target unknowntarget not found`, 189 task: modifyTask(func(t *api.Task) { 190 t.Spec = api.TaskSpec{ 191 Runtime: &api.TaskSpec_Container{ 192 Container: &api.ContainerSpec{ 193 Secrets: []*api.SecretReference{ 194 { 195 SecretID: "templatedsecret", 196 SecretName: "templatedsecretname", 197 }, 198 }, 199 }, 200 }, 201 } 202 }), 203 node: modifyNode(func(n *api.NodeDescription) { 204 // use default values 205 }), 206 }, 207 { 208 desc: "Test that expansion of the same secret avoids recursion", 209 secretSpec: api.SecretSpec{ 210 Data: []byte("SECRET_VAL={{secret \"templatedsecrettarget\"}}\n"), 211 Templating: &api.Driver{Name: "golang"}, 212 }, 213 expected: "SECRET_VAL=SECRET_VAL={{secret \"templatedsecrettarget\"}}\n\n", 214 task: modifyTask(func(t *api.Task) { 215 t.Spec = api.TaskSpec{ 216 Runtime: &api.TaskSpec_Container{ 217 Container: &api.ContainerSpec{ 218 Secrets: []*api.SecretReference{ 219 { 220 SecretID: "templatedsecret", 221 SecretName: "templatedsecretname", 222 Target: &api.SecretReference_File{ 223 File: &api.FileTarget{ 224 Name: "templatedsecrettarget", 225 UID: "0", 226 GID: "0", 227 Mode: 0666, 228 }, 229 }, 230 }, 231 }, 232 }, 233 }, 234 } 235 }), 236 node: modifyNode(func(n *api.NodeDescription) { 237 // use default values 238 }), 239 }, 240 { 241 desc: "Test env", 242 secretSpec: api.SecretSpec{ 243 Data: []byte("ENV VALUE={{env \"foo\"}}\n" + 244 "DOES NOT EXIST={{env \"badname\"}}\n"), 245 Templating: &api.Driver{Name: "golang"}, 246 }, 247 expected: "ENV VALUE=bar\n" + 248 "DOES NOT EXIST=\n", 249 task: modifyTask(func(t *api.Task) { 250 t.Spec = api.TaskSpec{ 251 Runtime: &api.TaskSpec_Container{ 252 Container: &api.ContainerSpec{ 253 Secrets: []*api.SecretReference{ 254 { 255 SecretID: "templatedsecret", 256 SecretName: "templatedsecretname", 257 }, 258 }, 259 Env: []string{"foo=bar"}, 260 }, 261 }, 262 } 263 }), 264 node: modifyNode(func(n *api.NodeDescription) { 265 // use default values 266 }), 267 }, 268 } 269 270 for _, testCase := range testCases { 271 templatedSecret.Spec = testCase.secretSpec 272 273 dependencyManager := agent.NewDependencyManager() 274 dependencyManager.Secrets().Add(*templatedSecret, *referencedSecret) 275 dependencyManager.Configs().Add(*referencedConfig) 276 277 templatedDependencies := NewTemplatedDependencyGetter(agent.Restrict(dependencyManager, testCase.task), testCase.task, testCase.node) 278 expandedSecret, err := templatedDependencies.Secrets().Get("templatedsecret") 279 280 if testCase.expectedErr != "" { 281 assert.EqualError(t, err, testCase.expectedErr) 282 } else { 283 assert.NoError(t, err) 284 require.NotNil(t, expandedSecret) 285 assert.Equal(t, testCase.expected, string(expandedSecret.Spec.Data), testCase.desc) 286 } 287 } 288 } 289 290 func TestTemplatedConfig(t *testing.T) { 291 templatedConfig := &api.Config{ 292 ID: "templatedconfig", 293 } 294 295 referencedSecret := &api.Secret{ 296 ID: "referencedsecret", 297 Spec: api.SecretSpec{ 298 Data: []byte("mysecret"), 299 }, 300 } 301 referencedConfig := &api.Config{ 302 ID: "referencedconfig", 303 Spec: api.ConfigSpec{ 304 Data: []byte("myconfig"), 305 }, 306 } 307 308 type testCase struct { 309 desc string 310 configSpec api.ConfigSpec 311 task *api.Task 312 expected string 313 expectedErr string 314 expectedSensitive bool 315 node *api.NodeDescription 316 } 317 318 testCases := []testCase{ 319 { 320 desc: "Test expansion of task context", 321 configSpec: api.ConfigSpec{ 322 Data: []byte("SERVICE_ID={{.Service.ID}}\n" + 323 "SERVICE_NAME={{.Service.Name}}\n" + 324 "TASK_ID={{.Task.ID}}\n" + 325 "TASK_NAME={{.Task.Name}}\n" + 326 "NODE_ID={{.Node.ID}}\n" + 327 "NODE_HOSTNAME={{.Node.Hostname}}\n" + 328 "NODE_OS={{.Node.Platform.OS}}\n" + 329 "NODE_ARCHITECTURE={{.Node.Platform.Architecture}}"), 330 Templating: &api.Driver{Name: "golang"}, 331 }, 332 expected: "SERVICE_ID=serviceID\n" + 333 "SERVICE_NAME=serviceName\n" + 334 "TASK_ID=taskID\n" + 335 "TASK_NAME=serviceName.10.taskID\n" + 336 "NODE_ID=nodeID\n" + 337 "NODE_HOSTNAME=myhostname\n" + 338 "NODE_OS=testOS\n" + 339 "NODE_ARCHITECTURE=testArchitecture", 340 task: modifyTask(func(t *api.Task) { 341 t.Spec = api.TaskSpec{ 342 Runtime: &api.TaskSpec_Container{ 343 Container: &api.ContainerSpec{ 344 Configs: []*api.ConfigReference{ 345 { 346 ConfigID: "templatedconfig", 347 ConfigName: "templatedconfigname", 348 }, 349 }, 350 }, 351 }, 352 } 353 }), 354 node: modifyNode(func(n *api.NodeDescription) { 355 n.Hostname = "myhostname" 356 n.Platform.OS = "testOS" 357 n.Platform.Architecture = "testArchitecture" 358 }), 359 }, 360 { 361 desc: "Test expansion of secret, by target", 362 configSpec: api.ConfigSpec{ 363 Data: []byte("SECRET_VAL={{secret \"referencedsecrettarget\"}}\n"), 364 Templating: &api.Driver{Name: "golang"}, 365 }, 366 expected: "SECRET_VAL=mysecret\n", 367 expectedSensitive: true, 368 task: modifyTask(func(t *api.Task) { 369 t.Spec = api.TaskSpec{ 370 Runtime: &api.TaskSpec_Container{ 371 Container: &api.ContainerSpec{ 372 Secrets: []*api.SecretReference{ 373 { 374 SecretID: "referencedsecret", 375 SecretName: "referencedsecretname", 376 Target: &api.SecretReference_File{ 377 File: &api.FileTarget{ 378 Name: "referencedsecrettarget", 379 UID: "0", 380 GID: "0", 381 Mode: 0666, 382 }, 383 }, 384 }, 385 }, 386 Configs: []*api.ConfigReference{ 387 { 388 ConfigID: "templatedconfig", 389 ConfigName: "templatedconfigname", 390 }, 391 }, 392 }, 393 }, 394 } 395 }), 396 node: modifyNode(func(n *api.NodeDescription) { 397 // use default values 398 }), 399 }, 400 { 401 desc: "Test expansion of config, by target", 402 configSpec: api.ConfigSpec{ 403 Data: []byte("CONFIG_VAL={{config \"referencedconfigtarget\"}}\n"), 404 Templating: &api.Driver{Name: "golang"}, 405 }, 406 expected: "CONFIG_VAL=myconfig\n", 407 task: modifyTask(func(t *api.Task) { 408 t.Spec = api.TaskSpec{ 409 Runtime: &api.TaskSpec_Container{ 410 Container: &api.ContainerSpec{ 411 Configs: []*api.ConfigReference{ 412 { 413 ConfigID: "templatedconfig", 414 ConfigName: "templatedconfigname", 415 }, 416 { 417 ConfigID: "referencedconfig", 418 ConfigName: "referencedconfigname", 419 Target: &api.ConfigReference_File{ 420 File: &api.FileTarget{ 421 Name: "referencedconfigtarget", 422 UID: "0", 423 GID: "0", 424 Mode: 0666, 425 }, 426 }, 427 }, 428 }, 429 }, 430 }, 431 } 432 }), 433 node: modifyNode(func(n *api.NodeDescription) { 434 // use default values 435 }), 436 }, 437 { 438 desc: "Test expansion of secret not available to task", 439 configSpec: api.ConfigSpec{ 440 Data: []byte("SECRET_VAL={{secret \"unknowntarget\"}}\n"), 441 Templating: &api.Driver{Name: "golang"}, 442 }, 443 expectedErr: `failed to expand templated config templatedconfig: template: expansion:1:13: executing "expansion" at <secret "unknowntarget">: error calling secret: secret target unknowntarget not found`, 444 task: modifyTask(func(t *api.Task) { 445 t.Spec = api.TaskSpec{ 446 Runtime: &api.TaskSpec_Container{ 447 Container: &api.ContainerSpec{ 448 Configs: []*api.ConfigReference{ 449 { 450 ConfigID: "templatedconfig", 451 ConfigName: "templatedconfigname", 452 }, 453 }, 454 }, 455 }, 456 } 457 }), 458 node: modifyNode(func(n *api.NodeDescription) { 459 // use default values 460 }), 461 }, 462 { 463 desc: "Test expansion of config not available to task", 464 configSpec: api.ConfigSpec{ 465 Data: []byte("CONFIG_VAL={{config \"unknowntarget\"}}\n"), 466 Templating: &api.Driver{Name: "golang"}, 467 }, 468 expectedErr: `failed to expand templated config templatedconfig: template: expansion:1:13: executing "expansion" at <config "unknowntarget">: error calling config: config target unknowntarget not found`, 469 task: modifyTask(func(t *api.Task) { 470 t.Spec = api.TaskSpec{ 471 Runtime: &api.TaskSpec_Container{ 472 Container: &api.ContainerSpec{ 473 Configs: []*api.ConfigReference{ 474 { 475 ConfigID: "templatedconfig", 476 ConfigName: "templatedconfigname", 477 }, 478 }, 479 }, 480 }, 481 } 482 }), 483 node: modifyNode(func(n *api.NodeDescription) { 484 // use default values 485 }), 486 }, 487 { 488 desc: "Test that expansion of the same config avoids recursion", 489 configSpec: api.ConfigSpec{ 490 Data: []byte("CONFIG_VAL={{config \"templatedconfigtarget\"}}\n"), 491 Templating: &api.Driver{Name: "golang"}, 492 }, 493 expected: "CONFIG_VAL=CONFIG_VAL={{config \"templatedconfigtarget\"}}\n\n", 494 task: modifyTask(func(t *api.Task) { 495 t.Spec = api.TaskSpec{ 496 Runtime: &api.TaskSpec_Container{ 497 Container: &api.ContainerSpec{ 498 Configs: []*api.ConfigReference{ 499 { 500 ConfigID: "templatedconfig", 501 ConfigName: "templatedconfigname", 502 Target: &api.ConfigReference_File{ 503 File: &api.FileTarget{ 504 Name: "templatedconfigtarget", 505 UID: "0", 506 GID: "0", 507 Mode: 0666, 508 }, 509 }, 510 }, 511 }, 512 }, 513 }, 514 } 515 }), 516 node: modifyNode(func(n *api.NodeDescription) { 517 // use default values 518 }), 519 }, 520 { 521 desc: "Test env", 522 configSpec: api.ConfigSpec{ 523 Data: []byte("ENV VALUE={{env \"foo\"}}\n" + 524 "DOES NOT EXIST={{env \"badname\"}}\n"), 525 Templating: &api.Driver{Name: "golang"}, 526 }, 527 expected: "ENV VALUE=bar\n" + 528 "DOES NOT EXIST=\n", 529 task: modifyTask(func(t *api.Task) { 530 t.Spec = api.TaskSpec{ 531 Runtime: &api.TaskSpec_Container{ 532 Container: &api.ContainerSpec{ 533 Configs: []*api.ConfigReference{ 534 { 535 ConfigID: "templatedconfig", 536 ConfigName: "templatedconfigname", 537 }, 538 }, 539 Env: []string{"foo=bar"}, 540 }, 541 }, 542 } 543 }), 544 node: modifyNode(func(n *api.NodeDescription) { 545 // use default values 546 }), 547 }, 548 } 549 550 for _, testCase := range testCases { 551 templatedConfig.Spec = testCase.configSpec 552 553 dependencyManager := agent.NewDependencyManager() 554 dependencyManager.Configs().Add(*templatedConfig, *referencedConfig) 555 dependencyManager.Secrets().Add(*referencedSecret) 556 557 templatedDependencies := NewTemplatedDependencyGetter(agent.Restrict(dependencyManager, testCase.task), testCase.task, testCase.node) 558 expandedConfig1, err1 := templatedDependencies.Configs().Get("templatedconfig") 559 expandedConfig2, sensitive, err2 := templatedDependencies.Configs().(TemplatedConfigGetter).GetAndFlagSecretData("templatedconfig") 560 561 if testCase.expectedErr != "" { 562 assert.EqualError(t, err1, testCase.expectedErr) 563 assert.EqualError(t, err2, testCase.expectedErr) 564 } else { 565 assert.NoError(t, err1) 566 assert.NoError(t, err2) 567 require.NotNil(t, expandedConfig1) 568 require.NotNil(t, expandedConfig2) 569 assert.Equal(t, testCase.expected, string(expandedConfig1.Spec.Data), testCase.desc) 570 assert.Equal(t, testCase.expected, string(expandedConfig2.Spec.Data), testCase.desc) 571 assert.Equal(t, testCase.expectedSensitive, sensitive, testCase.desc) 572 } 573 } 574 }