github.com/DelineaXPM/dsv-cli@v1.40.6/tests/e2e/cmd_init_test.go (about) 1 //go:build endtoend 2 // +build endtoend 3 4 package e2e 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "path/filepath" 10 "runtime" 11 "testing" 12 "time" 13 ) 14 15 func TestInitWithNoConfig(t *testing.T) { 16 if runtime.GOOS == "windows" { 17 t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.") 18 } 19 e := newEnv() 20 21 var ( 22 config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml") 23 ) 24 25 defer func() { deleteFile(t, config) }() 26 27 cmd := []string{ 28 "init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config), 29 } 30 31 runFlow(t, cmd, func(c console) { 32 c.ExpectString("Please enter tenant name") 33 c.SendLine(e.tenant) 34 35 c.ExpectString("Please select store type") 36 c.SendKeyEnter() 37 38 c.ExpectString("Please enter directory for file store") 39 c.SendKeyEnter() 40 41 c.ExpectString("Please enter cache strategy for secrets") 42 c.SendKeyEnter() 43 44 c.ExpectString("Please enter auth type") 45 c.SendKeyEnter() 46 47 c.ExpectString("Please enter username") 48 c.SendLine(e.username) 49 50 c.ExpectString("Please enter password") 51 c.SendLine(e.password) 52 53 c.ExpectEOF() 54 }) 55 56 got := readFile(t, config) 57 requireLine(t, got, "default:") 58 requireLine(t, got, "auth:") 59 requireLine(t, got, "type: password") 60 requireLine(t, got, fmt.Sprintf("username: %s", e.username)) 61 requireLine(t, got, "cache:") 62 requireLine(t, got, "strategy: server") 63 requireLine(t, got, fmt.Sprintf("domain: %s", e.domain)) 64 requireLine(t, got, "store:") 65 requireLine(t, got, "type: file") 66 requireLine(t, got, fmt.Sprintf("tenant: %s", e.tenant)) 67 } 68 69 func TestInitWithExistingConfig(t *testing.T) { 70 if runtime.GOOS == "windows" { 71 t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.") 72 } 73 e := newEnv() 74 75 const ( 76 profileName = "automation" 77 cacheAge = "5" 78 ) 79 var ( 80 config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml") 81 ) 82 83 createFile(t, config) 84 defer func() { deleteFile(t, config) }() 85 86 cmd := []string{ 87 "init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config), 88 } 89 90 runFlow(t, cmd, func(c console) { 91 c.ExpectString("Found an existing cli-config located at") 92 c.ExpectString("Select an option") 93 c.SendKeyArrowDown() 94 c.SendKeyArrowDown() 95 c.SendKeyEnter() 96 97 c.ExpectString("Please enter profile name") 98 c.SendLine(profileName) 99 100 c.ExpectString("Please enter tenant name") 101 c.SendLine(e.tenant) 102 103 c.ExpectString("Please select store type") 104 c.SendKeyEnter() 105 106 c.ExpectString("Please enter directory for file store") 107 c.SendKeyEnter() 108 109 c.ExpectString("Please enter cache strategy for secrets") 110 c.SendKeyArrowDown() 111 c.SendKeyArrowDown() 112 c.SendKeyEnter() 113 114 c.ExpectString("Please enter cache age (minutes until expiration)") 115 c.SendLine("a") 116 117 c.ExpectString("Sorry, your reply was invalid: Unable to parse age.") 118 c.SendLine("-2") 119 120 c.ExpectString("Sorry, your reply was invalid: Unable to parse age.") 121 c.SendLine("0") 122 123 c.ExpectString("Sorry, your reply was invalid: Unable to parse age.") 124 c.SendLine(cacheAge) 125 126 c.ExpectString("Please enter auth type") 127 c.SendKeyEnter() 128 129 c.ExpectString("Please enter username") 130 c.SendLine(e.username) 131 132 c.ExpectString("Please enter password") 133 c.SendLine(e.password) 134 135 c.ExpectEOF() 136 }) 137 138 got := readFile(t, config) 139 requireLine(t, got, fmt.Sprintf("%s:", profileName)) 140 requireLine(t, got, "auth:") 141 requireLine(t, got, "type: password") 142 requireLine(t, got, fmt.Sprintf("username: %s", e.username)) 143 requireLine(t, got, "cache:") 144 requireLine(t, got, fmt.Sprintf("age: %s", cacheAge)) 145 requireLine(t, got, "strategy: cache.server") 146 requireLine(t, got, fmt.Sprintf("domain: %s", e.domain)) 147 requireLine(t, got, "store:") 148 requireLine(t, got, "type: file") 149 requireLine(t, got, fmt.Sprintf("tenant: %s", e.tenant)) 150 } 151 152 func TestInitOverwriteExistingConfig(t *testing.T) { 153 if runtime.GOOS == "windows" { 154 t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.") 155 } 156 e := newEnv() 157 158 var ( 159 config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml") 160 ) 161 162 createFile(t, config) 163 defer func() { deleteFile(t, config) }() 164 165 cmd := []string{ 166 "init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config), 167 } 168 169 runFlow(t, cmd, func(c console) { 170 c.ExpectString("Found an existing cli-config located at") 171 c.ExpectString("Select an option") 172 c.SendKeyArrowDown() 173 c.SendKeyEnter() 174 175 c.ExpectString("Please enter profile name") 176 c.SendKeyEnter() 177 178 c.ExpectString("Please enter tenant name") 179 c.SendLine(e.tenant) 180 181 c.ExpectString("Please select store type") 182 c.SendKeyEnter() 183 184 c.ExpectString("Please enter directory for file store") 185 c.SendKeyEnter() 186 187 c.ExpectString("Please enter cache strategy for secrets") 188 c.SendKeyEnter() 189 190 c.ExpectString("Please enter auth type") 191 c.SendKeyEnter() 192 193 c.ExpectString("Please enter username") 194 c.SendLine(e.username) 195 196 c.ExpectString("Please enter password") 197 c.SendLine(e.password) 198 199 c.ExpectEOF() 200 }) 201 202 got := readFile(t, config) 203 requireLine(t, got, "default:") 204 requireLine(t, got, "auth:") 205 requireLine(t, got, "type: password") 206 requireLine(t, got, fmt.Sprintf("username: %s", e.username)) 207 requireLine(t, got, "cache:") 208 requireLine(t, got, "strategy: server") 209 requireLine(t, got, fmt.Sprintf("domain: %s", e.domain)) 210 requireLine(t, got, "store:") 211 requireLine(t, got, "type: file") 212 requireLine(t, got, fmt.Sprintf("tenant: %s", e.tenant)) 213 } 214 215 func TestInitAuthFails(t *testing.T) { 216 if runtime.GOOS == "windows" { 217 t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.") 218 } 219 e := newEnv() 220 221 var ( 222 config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml") 223 ) 224 225 createFile(t, config) 226 defer func() { deleteFile(t, config) }() 227 228 cmd := []string{ 229 "init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config), 230 } 231 232 runFlow(t, cmd, func(c console) { 233 c.ExpectString("Found an existing cli-config located at") 234 c.ExpectString("Select an option") 235 c.SendKeyArrowDown() 236 c.SendKeyArrowDown() 237 c.SendKeyEnter() 238 239 c.ExpectString("Please enter profile name") 240 c.SendLine("automation") 241 242 c.ExpectString("Please enter tenant name") 243 c.SendLine(e.tenant) 244 245 c.ExpectString("Please select store type") 246 c.SendKeyEnter() 247 248 c.ExpectString("Please enter directory for file store") 249 c.SendKeyEnter() 250 251 c.ExpectString("Please enter cache strategy for secrets") 252 c.SendKeyEnter() 253 254 c.ExpectString("Please enter auth type") 255 c.SendKeyEnter() 256 257 c.ExpectString("Please enter username") 258 c.SendLine("random-username-that-definitely-does-not-exist") 259 260 c.ExpectString("Please enter password") 261 c.SendLine("n0t-a-Stronges-P@assWord") 262 263 c.ExpectString("Failed to authenticate, restoring previous config.") 264 c.ExpectEOF() 265 }) 266 } 267 268 func TestInitAWSInvalid(t *testing.T) { 269 if runtime.GOOS == "windows" { 270 t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.") 271 } 272 e := newEnv() 273 274 var ( 275 config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml") 276 ) 277 278 createFile(t, config) 279 defer func() { deleteFile(t, config) }() 280 281 cmd := []string{ 282 "init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config), 283 } 284 285 runFlow(t, cmd, func(c console) { 286 c.ExpectString("Found an existing cli-config located at") 287 c.ExpectString("Select an option") 288 c.SendKeyArrowDown() 289 c.SendKeyEnter() 290 291 c.ExpectString("Please enter profile name") 292 c.SendKeyEnter() 293 294 c.ExpectString("Please enter tenant name") 295 c.SendLine(e.tenant) 296 297 c.ExpectString("Please select store type") 298 c.SendKeyEnter() 299 300 c.ExpectString("Please enter directory for file store") 301 c.SendKeyEnter() 302 303 c.ExpectString("Please enter cache strategy for secrets") 304 c.SendKeyEnter() 305 306 c.ExpectString("Please enter auth type") 307 c.SendKeyArrowDown() 308 c.SendKeyArrowDown() 309 c.SendKeyArrowDown() 310 c.SendKeyEnter() 311 312 c.ExpectString("Please enter aws profile for federated aws auth") 313 c.SendLine("not-a-real-profile") 314 315 c.ExpectString("Failed to authenticate, restoring previous config.") 316 c.ExpectEOF() 317 }) 318 } 319 320 func TestInitClientCredsInvalid(t *testing.T) { 321 if runtime.GOOS == "windows" { 322 t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.") 323 } 324 e := newEnv() 325 326 var ( 327 config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml") 328 ) 329 330 createFile(t, config) 331 defer func() { deleteFile(t, config) }() 332 333 cmd := []string{ 334 "init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config), 335 } 336 337 runFlow(t, cmd, func(c console) { 338 c.ExpectString("Found an existing cli-config located at") 339 c.ExpectString("Select an option") 340 c.SendKeyArrowDown() 341 c.SendKeyEnter() 342 343 c.ExpectString("Please enter profile name") 344 c.SendKeyEnter() 345 346 c.ExpectString("Please enter tenant name") 347 c.SendLine(e.tenant) 348 349 c.ExpectString("Please select store type") 350 c.SendKeyEnter() 351 352 c.ExpectString("Please enter directory for file store") 353 c.SendKeyEnter() 354 355 c.ExpectString("Please enter cache strategy for secrets") 356 c.SendKeyEnter() 357 358 c.ExpectString("Please enter auth type") 359 c.SendKeyArrowDown() 360 c.SendKeyEnter() 361 362 c.ExpectString("Please enter client id for client auth") 363 c.SendLine("not-a-real-client-id") 364 365 c.ExpectString("Please enter client secret for client auth") 366 c.SendLine("not-a-real-client-secret") 367 368 c.ExpectString("Failed to authenticate, restoring previous config.") 369 c.ExpectEOF() 370 }) 371 } 372 373 func TestInitProfileExists(t *testing.T) { 374 if runtime.GOOS == "windows" { 375 t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.") 376 } 377 e := newEnv() 378 379 var ( 380 config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml") 381 ) 382 383 defer func() { deleteFile(t, config) }() 384 385 cmd := []string{ 386 "init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config), 387 } 388 389 runFlow(t, cmd, func(c console) { 390 c.ExpectString("Please enter tenant name") 391 c.SendLine(e.tenant) 392 393 c.ExpectString("Please select store type") 394 c.SendKeyEnter() 395 396 c.ExpectString("Please enter directory for file store") 397 c.SendKeyEnter() 398 399 c.ExpectString("Please enter cache strategy for secrets") 400 c.SendKeyEnter() 401 402 c.ExpectString("Please enter auth type") 403 c.SendKeyEnter() 404 405 c.ExpectString("Please enter username") 406 c.SendLine(e.username) 407 408 c.ExpectString("Please enter password") 409 c.SendLine(e.password) 410 411 c.ExpectEOF() 412 }) 413 414 cmd = []string{ 415 "init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config), "--profile=default", 416 } 417 418 runFlow(t, cmd, func(c console) { 419 c.ExpectString("Profile \"default\" already exists in the config.") 420 c.ExpectEOF() 421 }) 422 } 423 424 func TestInitWrongStoreType(t *testing.T) { 425 if runtime.GOOS == "windows" { 426 t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.") 427 } 428 e := newEnv() 429 430 var ( 431 config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml") 432 ) 433 434 cmd := []string{ 435 "init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config), 436 } 437 438 runFlow(t, cmd, func(c console) { 439 c.ExpectString("Please enter tenant name") 440 c.SendLine(e.tenant) 441 442 c.ExpectString("Please select store type") 443 c.SendKeyArrowDown() 444 c.SendKeyArrowDown() 445 c.SendKeyArrowDown() 446 c.SendKeyEnter() 447 448 c.ExpectString("Failed to get store: 'wincred' option for store.type is supported on windows only.") 449 c.ExpectEOF() 450 }) 451 } 452 453 func TestInitWithNoStore(t *testing.T) { 454 if runtime.GOOS == "windows" { 455 t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.") 456 } 457 e := newEnv() 458 459 var ( 460 config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml") 461 ) 462 463 defer func() { deleteFile(t, config) }() 464 465 cmd := []string{ 466 "init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config), 467 } 468 469 runFlow(t, cmd, func(c console) { 470 c.ExpectString("Please enter tenant name") 471 c.SendLine(e.tenant) 472 473 c.ExpectString("Please select store type") 474 c.SendKeyArrowDown() 475 c.SendKeyEnter() 476 477 c.ExpectString("Please enter auth type") 478 c.SendKeyEnter() 479 480 c.ExpectString("CLI configuration file successfully saved.") 481 c.ExpectEOF() 482 }) 483 484 got := readFile(t, config) 485 requireLine(t, got, "default:") 486 requireLine(t, got, "auth:") 487 requireLine(t, got, "type: password") 488 requireLine(t, got, fmt.Sprintf("domain: %s", e.domain)) 489 requireLine(t, got, "store:") 490 requireLine(t, got, "type: none") 491 requireLine(t, got, fmt.Sprintf("tenant: %s", e.tenant)) 492 } 493 494 func TestInitUsingCertificateFileData(t *testing.T) { 495 if runtime.GOOS == "windows" { 496 t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.") 497 } 498 e := newEnv() 499 500 const ( 501 profileName = "file-cert-data" 502 cacheAge = "5" 503 ) 504 var ( 505 config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml") 506 certPath = filepath.Join(e.tmpDirPath, "e2e-cert-data.json") 507 ) 508 509 certData, err := json.Marshal(&struct { 510 Certificate string `json:"certificate"` 511 PrivateKey string `json:"privateKey"` 512 SshPublicKey string `json:"sshPublicKey"` 513 }{ 514 Certificate: e.certificate, 515 PrivateKey: e.privateKey, 516 SshPublicKey: "ssh-key", 517 }) 518 if err != nil { 519 t.Fatalf("json.Marshal(%q) = %v", certData, err) 520 } 521 522 createFile(t, config) 523 defer func() { deleteFile(t, config) }() 524 525 writeFile(t, certData, certPath) 526 defer func() { deleteFile(t, certPath) }() 527 528 cmd := []string{ 529 "init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config), 530 } 531 532 runFlow(t, cmd, func(c console) { 533 c.ExpectString("Found an existing cli-config located at") 534 c.ExpectString("Select an option") 535 c.SendKeyArrowDown() 536 c.SendKeyArrowDown() 537 c.SendKeyEnter() 538 539 c.ExpectString("Please enter profile name") 540 c.SendLine(profileName) 541 542 c.ExpectString("Please enter tenant name") 543 c.SendLine(e.tenant) 544 545 c.ExpectString("Please select store type") 546 c.SendKeyEnter() 547 548 c.ExpectString("Please enter directory for file store") 549 c.SendKeyEnter() 550 551 c.ExpectString("Please enter cache strategy for secrets") 552 c.SendKeyArrowDown() 553 c.SendKeyArrowDown() 554 c.SendKeyEnter() 555 556 c.ExpectString("Please enter cache age (minutes until expiration)") 557 c.SendLine(cacheAge) 558 559 c.ExpectString("Please enter auth type") 560 c.SendKeyArrowDown() 561 c.SendKeyArrowDown() 562 c.SendKeyArrowDown() 563 c.SendKeyArrowDown() 564 c.SendKeyArrowDown() 565 c.SendKeyArrowDown() 566 c.SendKeyArrowDown() 567 c.SendKeyEnter() 568 569 c.ExpectString("Raw certificate") 570 c.SendKeyArrowDown() 571 c.SendKeyEnter() 572 573 c.ExpectString("Certificate file path:") 574 time.Sleep(time.Millisecond * 10) 575 c.SendLine(certPath) 576 577 c.ExpectString("Raw private key") 578 c.SendKeyArrowDown() 579 c.SendKeyEnter() 580 581 c.ExpectString("Private key file path:") 582 time.Sleep(time.Millisecond * 10) 583 c.SendLine(certPath) 584 585 c.ExpectEOF() 586 }) 587 588 got := readFile(t, config) 589 requireLine(t, got, fmt.Sprintf("%s:", profileName)) 590 requireLine(t, got, "auth:") 591 requireLine(t, got, "type: cert") 592 requireLine(t, got, fmt.Sprintf("certificate: %s", e.certificate)) 593 requireLine(t, got, fmt.Sprintf("privateKey: %s", e.privateKey)) 594 requireLine(t, got, "cache:") 595 requireLine(t, got, fmt.Sprintf("age: %s", cacheAge)) 596 requireLine(t, got, "strategy: cache.server") 597 requireLine(t, got, fmt.Sprintf("domain: %s", e.domain)) 598 requireLine(t, got, "store:") 599 requireLine(t, got, "type: file") 600 requireLine(t, got, fmt.Sprintf("tenant: %s", e.tenant)) 601 }