github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/builder/azure/arm/config_test.go (about) 1 package arm 2 3 import ( 4 "fmt" 5 "strings" 6 "testing" 7 "time" 8 9 "github.com/Azure/azure-sdk-for-go/arm/compute" 10 "github.com/hashicorp/packer/builder/azure/common/constants" 11 "github.com/hashicorp/packer/packer" 12 ) 13 14 // List of configuration parameters that are required by the ARM builder. 15 var requiredConfigValues = []string{ 16 "capture_name_prefix", 17 "capture_container_name", 18 "client_id", 19 "client_secret", 20 "image_offer", 21 "image_publisher", 22 "image_sku", 23 "location", 24 "os_type", 25 "storage_account", 26 "resource_group_name", 27 "subscription_id", 28 } 29 30 func TestConfigShouldProvideReasonableDefaultValues(t *testing.T) { 31 c, _, err := newConfig(getArmBuilderConfiguration(), getPackerConfiguration()) 32 33 if err != nil { 34 t.Error("Expected configuration creation to succeed, but it failed!\n") 35 t.Fatalf(" errors: %s\n", err) 36 } 37 38 if c.UserName == "" { 39 t.Error("Expected 'UserName' to be populated, but it was empty!") 40 } 41 42 if c.VMSize == "" { 43 t.Error("Expected 'VMSize' to be populated, but it was empty!") 44 } 45 46 if c.ObjectID != "" { 47 t.Errorf("Expected 'ObjectID' to be nil, but it was '%s'!", c.ObjectID) 48 } 49 50 if c.managedImageStorageAccountType == "" { 51 t.Errorf("Expected 'managedImageStorageAccountType' to be populated, but it was empty!") 52 } 53 } 54 55 func TestConfigShouldBeAbleToOverrideDefaultedValues(t *testing.T) { 56 builderValues := getArmBuilderConfiguration() 57 builderValues["ssh_password"] = "override_password" 58 builderValues["ssh_username"] = "override_username" 59 builderValues["vm_size"] = "override_vm_size" 60 builderValues["communicator"] = "ssh" 61 builderValues["managed_image_storage_account_type"] = "Premium_LRS" 62 63 c, _, err := newConfig(builderValues, getPackerConfiguration()) 64 65 if err != nil { 66 t.Fatalf("newConfig failed: %s", err) 67 } 68 69 if c.Password != "override_password" { 70 t.Errorf("Expected 'Password' to be set to 'override_password', but found %q!", c.Password) 71 } 72 73 if c.Comm.SSHPassword != "override_password" { 74 t.Errorf("Expected 'c.Comm.SSHPassword' to be set to 'override_password', but found %q!", c.Comm.SSHPassword) 75 } 76 77 if c.UserName != "override_username" { 78 t.Errorf("Expected 'UserName' to be set to 'override_username', but found %q!", c.UserName) 79 } 80 81 if c.Comm.SSHUsername != "override_username" { 82 t.Errorf("Expected 'c.Comm.SSHUsername' to be set to 'override_username', but found %q!", c.Comm.SSHUsername) 83 } 84 85 if c.VMSize != "override_vm_size" { 86 t.Errorf("Expected 'vm_size' to be set to 'override_vm_size', but found %q!", c.VMSize) 87 } 88 89 if c.managedImageStorageAccountType != compute.PremiumLRS { 90 t.Errorf("Expected 'managed_image_storage_account_type' to be set to 'Premium_LRS', but found %q!", c.managedImageStorageAccountType) 91 } 92 } 93 94 func TestConfigShouldDefaultVMSizeToStandardA1(t *testing.T) { 95 c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration()) 96 97 if c.VMSize != "Standard_A1" { 98 t.Errorf("Expected 'VMSize' to default to 'Standard_A1', but got '%s'.", c.VMSize) 99 } 100 } 101 102 func TestConfigShouldDefaultImageVersionToLatest(t *testing.T) { 103 c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration()) 104 105 if c.ImageVersion != "latest" { 106 t.Errorf("Expected 'ImageVersion' to default to 'latest', but got '%s'.", c.ImageVersion) 107 } 108 } 109 110 func TestConfigShouldNotDefaultImageVersionIfCustomImage(t *testing.T) { 111 config := map[string]string{ 112 "capture_name_prefix": "ignore", 113 "capture_container_name": "ignore", 114 "location": "ignore", 115 "image_url": "ignore", 116 "storage_account": "ignore", 117 "resource_group_name": "ignore", 118 "subscription_id": "ignore", 119 "os_type": constants.Target_Linux, 120 "communicator": "none", 121 } 122 123 c, _, _ := newConfig(config, getPackerConfiguration()) 124 if c.ImageVersion != "" { 125 t.Errorf("Expected 'ImageVersion' to empty, but got '%s'.", c.ImageVersion) 126 } 127 } 128 129 func TestConfigShouldNormalizeOSTypeCase(t *testing.T) { 130 config := map[string]string{ 131 "capture_name_prefix": "ignore", 132 "capture_container_name": "ignore", 133 "location": "ignore", 134 "image_url": "ignore", 135 "storage_account": "ignore", 136 "resource_group_name": "ignore", 137 "subscription_id": "ignore", 138 "communicator": "none", 139 } 140 141 os_types := map[string][]string{ 142 constants.Target_Linux: {"linux", "LiNuX"}, 143 constants.Target_Windows: {"windows", "WiNdOWs"}, 144 } 145 146 for k, v := range os_types { 147 for _, os_type := range v { 148 config["os_type"] = os_type 149 c, _, err := newConfig(config, getPackerConfiguration()) 150 if err != nil { 151 t.Fatalf("Expected config to accept the value %q, but it did not", os_type) 152 } 153 154 if c.OSType != k { 155 t.Fatalf("Expected config to normalize the value %q to %q, but it did not", os_type, constants.Target_Linux) 156 } 157 } 158 } 159 160 bad_os_types := []string{"", "does-not-exist"} 161 for _, os_type := range bad_os_types { 162 config["os_type"] = os_type 163 _, _, err := newConfig(config, getPackerConfiguration()) 164 if err == nil { 165 t.Fatalf("Expected config to not accept the value %q, but it did", os_type) 166 } 167 } 168 } 169 170 func TestConfigShouldRejectCustomImageAndMarketPlace(t *testing.T) { 171 config := map[string]string{ 172 "capture_name_prefix": "ignore", 173 "capture_container_name": "ignore", 174 "location": "ignore", 175 "image_url": "ignore", 176 "resource_group_name": "ignore", 177 "storage_account": "ignore", 178 "subscription_id": "ignore", 179 "os_type": constants.Target_Linux, 180 "communicator": "none", 181 } 182 packerConfiguration := getPackerConfiguration() 183 marketPlace := []string{"image_publisher", "image_offer", "image_sku"} 184 185 for _, x := range marketPlace { 186 config[x] = "ignore" 187 _, _, err := newConfig(config, packerConfiguration) 188 if err == nil { 189 t.Errorf("Expected Config to reject image_url and %s, but it did not", x) 190 } 191 } 192 } 193 194 func TestConfigVirtualNetworkNameIsOptional(t *testing.T) { 195 config := map[string]string{ 196 "capture_name_prefix": "ignore", 197 "capture_container_name": "ignore", 198 "location": "ignore", 199 "image_url": "ignore", 200 "storage_account": "ignore", 201 "resource_group_name": "ignore", 202 "subscription_id": "ignore", 203 "os_type": constants.Target_Linux, 204 "communicator": "none", 205 "virtual_network_name": "MyVirtualNetwork", 206 } 207 208 c, _, _ := newConfig(config, getPackerConfiguration()) 209 if c.VirtualNetworkName != "MyVirtualNetwork" { 210 t.Errorf("Expected Config to set virtual_network_name to MyVirtualNetwork, but got %q", c.VirtualNetworkName) 211 } 212 if c.VirtualNetworkResourceGroupName != "" { 213 t.Errorf("Expected Config to leave virtual_network_resource_group_name to '', but got %q", c.VirtualNetworkResourceGroupName) 214 } 215 if c.VirtualNetworkSubnetName != "" { 216 t.Errorf("Expected Config to leave virtual_network_subnet_name to '', but got %q", c.VirtualNetworkSubnetName) 217 } 218 } 219 220 // The user can pass the value virtual_network_resource_group_name to avoid the lookup of 221 // a virtual network's resource group, or to help with disambiguation. The value should 222 // only be set if virtual_network_name was set. 223 func TestConfigVirtualNetworkResourceGroupNameMustBeSetWithVirtualNetworkName(t *testing.T) { 224 config := map[string]string{ 225 "capture_name_prefix": "ignore", 226 "capture_container_name": "ignore", 227 "location": "ignore", 228 "image_url": "ignore", 229 "storage_account": "ignore", 230 "resource_group_name": "ignore", 231 "subscription_id": "ignore", 232 "os_type": constants.Target_Linux, 233 "communicator": "none", 234 "virtual_network_resource_group_name": "MyVirtualNetworkRG", 235 } 236 237 _, _, err := newConfig(config, getPackerConfiguration()) 238 if err == nil { 239 t.Error("Expected Config to reject virtual_network_resource_group_name, if virtual_network_name is not set.") 240 } 241 } 242 243 // The user can pass the value virtual_network_subnet_name to avoid the lookup of 244 // a virtual network subnet's name, or to help with disambiguation. The value should 245 // only be set if virtual_network_name was set. 246 func TestConfigVirtualNetworkSubnetNameMustBeSetWithVirtualNetworkName(t *testing.T) { 247 config := map[string]string{ 248 "capture_name_prefix": "ignore", 249 "capture_container_name": "ignore", 250 "location": "ignore", 251 "image_url": "ignore", 252 "storage_account": "ignore", 253 "resource_group_name": "ignore", 254 "subscription_id": "ignore", 255 "os_type": constants.Target_Linux, 256 "communicator": "none", 257 "virtual_network_subnet_name": "MyVirtualNetworkRG", 258 } 259 260 _, _, err := newConfig(config, getPackerConfiguration()) 261 if err == nil { 262 t.Error("Expected Config to reject virtual_network_subnet_name, if virtual_network_name is not set.") 263 } 264 } 265 266 func TestConfigShouldDefaultToPublicCloud(t *testing.T) { 267 c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration()) 268 269 if c.CloudEnvironmentName != "Public" { 270 t.Errorf("Expected 'CloudEnvironmentName' to default to 'Public', but got '%s'.", c.CloudEnvironmentName) 271 } 272 273 if c.cloudEnvironment == nil || c.cloudEnvironment.Name != "AzurePublicCloud" { 274 t.Errorf("Expected 'cloudEnvironment' to be set to 'AzurePublicCloud', but got '%s'.", c.cloudEnvironment) 275 } 276 } 277 278 func TestConfigInstantiatesCorrectAzureEnvironment(t *testing.T) { 279 config := map[string]string{ 280 "capture_name_prefix": "ignore", 281 "capture_container_name": "ignore", 282 "image_offer": "ignore", 283 "image_publisher": "ignore", 284 "image_sku": "ignore", 285 "location": "ignore", 286 "storage_account": "ignore", 287 "resource_group_name": "ignore", 288 "subscription_id": "ignore", 289 "os_type": constants.Target_Linux, 290 "communicator": "none", 291 } 292 293 // user input is fun :) 294 var table = []struct { 295 name string 296 environmentName string 297 }{ 298 {"China", "AzureChinaCloud"}, 299 {"ChinaCloud", "AzureChinaCloud"}, 300 {"AzureChinaCloud", "AzureChinaCloud"}, 301 {"aZuReChInAcLoUd", "AzureChinaCloud"}, 302 303 {"USGovernment", "AzureUSGovernmentCloud"}, 304 {"USGovernmentCloud", "AzureUSGovernmentCloud"}, 305 {"AzureUSGovernmentCloud", "AzureUSGovernmentCloud"}, 306 {"aZuReUsGoVeRnMeNtClOuD", "AzureUSGovernmentCloud"}, 307 308 {"Public", "AzurePublicCloud"}, 309 {"PublicCloud", "AzurePublicCloud"}, 310 {"AzurePublicCloud", "AzurePublicCloud"}, 311 {"aZuRePuBlIcClOuD", "AzurePublicCloud"}, 312 } 313 314 packerConfiguration := getPackerConfiguration() 315 316 for _, x := range table { 317 config["cloud_environment_name"] = x.name 318 c, _, err := newConfig(config, packerConfiguration) 319 if err != nil { 320 t.Fatal(err) 321 } 322 323 if c.cloudEnvironment == nil || c.cloudEnvironment.Name != x.environmentName { 324 t.Errorf("Expected 'cloudEnvironment' to be set to '%s', but got '%s'.", x.environmentName, c.cloudEnvironment) 325 } 326 } 327 } 328 329 func TestUserShouldProvideRequiredValues(t *testing.T) { 330 builderValues := getArmBuilderConfiguration() 331 332 // Ensure we can successfully create a config. 333 _, _, err := newConfig(builderValues, getPackerConfiguration()) 334 if err != nil { 335 t.Error("Expected configuration creation to succeed, but it failed!\n") 336 t.Fatalf(" -> %+v\n", builderValues) 337 } 338 339 // Take away a required element, and ensure construction fails. 340 for _, v := range requiredConfigValues { 341 originalValue := builderValues[v] 342 delete(builderValues, v) 343 344 _, _, err := newConfig(builderValues, getPackerConfiguration()) 345 if err == nil { 346 t.Error("Expected configuration creation to fail, but it succeeded!\n") 347 t.Fatalf(" -> %+v\n", builderValues) 348 } 349 350 builderValues[v] = originalValue 351 } 352 } 353 354 func TestSystemShouldDefineRuntimeValues(t *testing.T) { 355 c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration()) 356 357 if c.Password == "" { 358 t.Errorf("Expected Password to not be empty, but it was '%s'!", c.Password) 359 } 360 361 if c.tmpComputeName == "" { 362 t.Errorf("Expected tmpComputeName to not be empty, but it was '%s'!", c.tmpComputeName) 363 } 364 365 if c.tmpDeploymentName == "" { 366 t.Errorf("Expected tmpDeploymentName to not be empty, but it was '%s'!", c.tmpDeploymentName) 367 } 368 369 if c.tmpResourceGroupName == "" { 370 t.Errorf("Expected tmpResourceGroupName to not be empty, but it was '%s'!", c.tmpResourceGroupName) 371 } 372 373 if c.tmpOSDiskName == "" { 374 t.Errorf("Expected tmpOSDiskName to not be empty, but it was '%s'!", c.tmpOSDiskName) 375 } 376 } 377 378 func TestConfigShouldTransformToVirtualMachineCaptureParameters(t *testing.T) { 379 c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration()) 380 parameters := c.toVirtualMachineCaptureParameters() 381 382 if *parameters.DestinationContainerName != c.CaptureContainerName { 383 t.Errorf("Expected DestinationContainerName to be equal to config's CaptureContainerName, but they were '%s' and '%s' respectively.", *parameters.DestinationContainerName, c.CaptureContainerName) 384 } 385 386 if *parameters.VhdPrefix != c.CaptureNamePrefix { 387 t.Errorf("Expected DestinationContainerName to be equal to config's CaptureContainerName, but they were '%s' and '%s' respectively.", *parameters.VhdPrefix, c.CaptureNamePrefix) 388 } 389 390 if *parameters.OverwriteVhds != false { 391 t.Error("Expected OverwriteVhds to be false, but it was not.") 392 } 393 } 394 395 func TestConfigShouldSupportPackersConfigElements(t *testing.T) { 396 c, _, err := newConfig( 397 getArmBuilderConfiguration(), 398 getPackerConfiguration(), 399 getPackerCommunicatorConfiguration()) 400 401 if err != nil { 402 t.Fatal(err) 403 } 404 405 if c.Comm.SSHTimeout != 1*time.Hour { 406 t.Errorf("Expected Comm.SSHTimeout to be a duration of an hour, but got '%s' instead.", c.Comm.SSHTimeout) 407 } 408 409 if c.Comm.WinRMTimeout != 2*time.Hour { 410 t.Errorf("Expected Comm.WinRMTimeout to be a durationof two hours, but got '%s' instead.", c.Comm.WinRMTimeout) 411 } 412 } 413 414 func TestWinRMConfigShouldSetRoundTripDecorator(t *testing.T) { 415 config := getArmBuilderConfiguration() 416 config["communicator"] = "winrm" 417 config["winrm_username"] = "username" 418 config["winrm_password"] = "password" 419 420 c, _, err := newConfig(config, getPackerConfiguration()) 421 if err != nil { 422 t.Fatal(err) 423 } 424 425 if c.Comm.WinRMTransportDecorator == nil { 426 t.Error("Expected WinRMTransportDecorator to be set, but it was nil") 427 } 428 } 429 430 func TestUserDeviceLoginIsEnabledForLinux(t *testing.T) { 431 config := map[string]string{ 432 "capture_name_prefix": "ignore", 433 "capture_container_name": "ignore", 434 "image_offer": "ignore", 435 "image_publisher": "ignore", 436 "image_sku": "ignore", 437 "location": "ignore", 438 "storage_account": "ignore", 439 "resource_group_name": "ignore", 440 "subscription_id": "ignore", 441 "os_type": constants.Target_Linux, 442 "communicator": "none", 443 } 444 445 _, _, err := newConfig(config, getPackerConfiguration()) 446 if err != nil { 447 t.Fatalf("failed to use device login for Linux: %s", err) 448 } 449 } 450 451 func TestUseDeviceLoginIsDisabledForWindows(t *testing.T) { 452 config := map[string]string{ 453 "capture_name_prefix": "ignore", 454 "capture_container_name": "ignore", 455 "image_offer": "ignore", 456 "image_publisher": "ignore", 457 "image_sku": "ignore", 458 "location": "ignore", 459 "storage_account": "ignore", 460 "resource_group_name": "ignore", 461 "subscription_id": "ignore", 462 "os_type": constants.Target_Windows, 463 "communicator": "none", 464 } 465 466 _, _, err := newConfig(config, getPackerConfiguration()) 467 if err == nil { 468 t.Fatal("Expected test to fail, but it succeeded") 469 } 470 471 multiError, _ := err.(*packer.MultiError) 472 if len(multiError.Errors) != 2 { 473 t.Errorf("Expected to find 2 errors, but found %d errors", len(multiError.Errors)) 474 } 475 476 if !strings.Contains(err.Error(), "client_id must be specified") { 477 t.Error("Expected to find error for 'client_id must be specified") 478 } 479 if !strings.Contains(err.Error(), "client_secret must be specified") { 480 t.Error("Expected to find error for 'client_secret must be specified") 481 } 482 } 483 484 func TestConfigShouldRejectMalformedCaptureNamePrefix(t *testing.T) { 485 config := map[string]string{ 486 "capture_container_name": "ignore", 487 "image_offer": "ignore", 488 "image_publisher": "ignore", 489 "image_sku": "ignore", 490 "location": "ignore", 491 "storage_account": "ignore", 492 "resource_group_name": "ignore", 493 "subscription_id": "ignore", 494 "communicator": "none", 495 // Does not matter for this test case, just pick one. 496 "os_type": constants.Target_Linux, 497 } 498 499 wellFormedCaptureNamePrefix := []string{ 500 "packer", 501 "AbcdefghijklmnopqrstuvwX", 502 "hypen-hypen", 503 "0leading-number", 504 "v1.core.local", 505 } 506 507 for _, x := range wellFormedCaptureNamePrefix { 508 config["capture_name_prefix"] = x 509 _, _, err := newConfig(config, getPackerConfiguration()) 510 511 if err != nil { 512 t.Errorf("Expected test to pass, but it failed with the well-formed capture_name_prefix set to %q.", x) 513 } 514 } 515 516 malformedCaptureNamePrefix := []string{ 517 "-leading-hypen", 518 "trailing-hypen-", 519 "trailing-period.", 520 "_leading-underscore", 521 "punc-!@#$%^&*()_+-=-punc", 522 "There-are-too-many-characters-in-the-name-and-the-limit-is-twenty-four", 523 } 524 525 for _, x := range malformedCaptureNamePrefix { 526 config["capture_name_prefix"] = x 527 _, _, err := newConfig(config, getPackerConfiguration()) 528 529 if err == nil { 530 t.Errorf("Expected test to fail, but it succeeded with the malformed capture_name_prefix set to %q.", x) 531 } 532 } 533 } 534 535 func TestConfigShouldRejectMalformedCaptureContainerName(t *testing.T) { 536 config := map[string]string{ 537 "capture_name_prefix": "ignore", 538 "image_offer": "ignore", 539 "image_publisher": "ignore", 540 "image_sku": "ignore", 541 "location": "ignore", 542 "storage_account": "ignore", 543 "resource_group_name": "ignore", 544 "subscription_id": "ignore", 545 "communicator": "none", 546 // Does not matter for this test case, just pick one. 547 "os_type": constants.Target_Linux, 548 } 549 550 wellFormedCaptureContainerName := []string{ 551 "0leading", 552 "aleading", 553 "hype-hypen", 554 "abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz", // 63 characters 555 } 556 557 for _, x := range wellFormedCaptureContainerName { 558 config["capture_container_name"] = x 559 _, _, err := newConfig(config, getPackerConfiguration()) 560 561 if err != nil { 562 t.Errorf("Expected test to pass, but it failed with the well-formed capture_container_name set to %q.", x) 563 } 564 } 565 566 malformedCaptureContainerName := []string{ 567 "No-Capitals", 568 "double--hypens", 569 "-leading-hypen", 570 "trailing-hypen-", 571 "punc-!@#$%^&*()_+-=-punc", 572 "there-are-over-63-characters-in-this-string-and-that-is-a-bad-container-name", 573 } 574 575 for _, x := range malformedCaptureContainerName { 576 config["capture_container_name"] = x 577 _, _, err := newConfig(config, getPackerConfiguration()) 578 579 if err == nil { 580 t.Errorf("Expected test to fail, but it succeeded with the malformed capture_container_name set to %q.", x) 581 } 582 } 583 } 584 585 func TestConfigShouldAcceptTags(t *testing.T) { 586 config := map[string]interface{}{ 587 "capture_name_prefix": "ignore", 588 "capture_container_name": "ignore", 589 "image_offer": "ignore", 590 "image_publisher": "ignore", 591 "image_sku": "ignore", 592 "location": "ignore", 593 "storage_account": "ignore", 594 "resource_group_name": "ignore", 595 "subscription_id": "ignore", 596 "communicator": "none", 597 // Does not matter for this test case, just pick one. 598 "os_type": constants.Target_Linux, 599 "azure_tags": map[string]string{ 600 "tag01": "value01", 601 "tag02": "value02", 602 }, 603 } 604 605 c, _, err := newConfig(config, getPackerConfiguration()) 606 607 if err != nil { 608 t.Fatal(err) 609 } 610 611 if len(c.AzureTags) != 2 { 612 t.Fatalf("expected to find 2 tags, but got %d", len(c.AzureTags)) 613 } 614 615 if _, ok := c.AzureTags["tag01"]; !ok { 616 t.Error("expected to find key=\"tag01\", but did not") 617 } 618 if _, ok := c.AzureTags["tag02"]; !ok { 619 t.Error("expected to find key=\"tag02\", but did not") 620 } 621 622 value := c.AzureTags["tag01"] 623 if *value != "value01" { 624 t.Errorf("expected AzureTags[\"tag01\"] to have value \"value01\", but got %q", value) 625 } 626 627 value = c.AzureTags["tag02"] 628 if *value != "value02" { 629 t.Errorf("expected AzureTags[\"tag02\"] to have value \"value02\", but got %q", value) 630 } 631 } 632 633 func TestConfigShouldRejectTagsInExcessOf15AcceptTags(t *testing.T) { 634 tooManyTags := map[string]string{} 635 for i := 0; i < 16; i++ { 636 tooManyTags[fmt.Sprintf("tag%.2d", i)] = "ignored" 637 } 638 639 config := map[string]interface{}{ 640 "capture_name_prefix": "ignore", 641 "capture_container_name": "ignore", 642 "image_offer": "ignore", 643 "image_publisher": "ignore", 644 "image_sku": "ignore", 645 "location": "ignore", 646 "storage_account": "ignore", 647 "resource_group_name": "ignore", 648 "subscription_id": "ignore", 649 "communicator": "none", 650 // Does not matter for this test case, just pick one. 651 "os_type": constants.Target_Linux, 652 "azure_tags": tooManyTags, 653 } 654 655 _, _, err := newConfig(config, getPackerConfiguration()) 656 657 if err == nil { 658 t.Fatal("expected config to reject based on an excessive amount of tags (> 15)") 659 } 660 } 661 662 func TestConfigShouldRejectExcessiveTagNameLength(t *testing.T) { 663 nameTooLong := make([]byte, 513) 664 for i := range nameTooLong { 665 nameTooLong[i] = 'a' 666 } 667 668 tags := map[string]string{} 669 tags[string(nameTooLong)] = "ignored" 670 671 config := map[string]interface{}{ 672 "capture_name_prefix": "ignore", 673 "capture_container_name": "ignore", 674 "image_offer": "ignore", 675 "image_publisher": "ignore", 676 "image_sku": "ignore", 677 "location": "ignore", 678 "storage_account": "ignore", 679 "resource_group_name": "ignore", 680 "subscription_id": "ignore", 681 "communicator": "none", 682 // Does not matter for this test case, just pick one. 683 "os_type": constants.Target_Linux, 684 "azure_tags": tags, 685 } 686 687 _, _, err := newConfig(config, getPackerConfiguration()) 688 if err == nil { 689 t.Fatal("expected config to reject tag name based on length (> 512)") 690 } 691 } 692 693 func TestConfigShouldRejectExcessiveTagValueLength(t *testing.T) { 694 valueTooLong := make([]byte, 257) 695 for i := range valueTooLong { 696 valueTooLong[i] = 'a' 697 } 698 699 tags := map[string]string{} 700 tags["tag01"] = string(valueTooLong) 701 702 config := map[string]interface{}{ 703 "capture_name_prefix": "ignore", 704 "capture_container_name": "ignore", 705 "image_offer": "ignore", 706 "image_publisher": "ignore", 707 "image_sku": "ignore", 708 "location": "ignore", 709 "storage_account": "ignore", 710 "resource_group_name": "ignore", 711 "subscription_id": "ignore", 712 "communicator": "none", 713 // Does not matter for this test case, just pick one. 714 "os_type": constants.Target_Linux, 715 "azure_tags": tags, 716 } 717 718 _, _, err := newConfig(config, getPackerConfiguration()) 719 if err == nil { 720 t.Fatal("expected config to reject tag value based on length (> 256)") 721 } 722 } 723 724 func TestConfigShouldRejectMissingCustomDataFile(t *testing.T) { 725 config := map[string]interface{}{ 726 "capture_name_prefix": "ignore", 727 "capture_container_name": "ignore", 728 "image_offer": "ignore", 729 "image_publisher": "ignore", 730 "image_sku": "ignore", 731 "location": "ignore", 732 "storage_account": "ignore", 733 "resource_group_name": "ignore", 734 "subscription_id": "ignore", 735 "communicator": "none", 736 // Does not matter for this test case, just pick one. 737 "os_type": constants.Target_Linux, 738 "custom_data_file": "/this/file/does/not/exist", 739 } 740 741 _, _, err := newConfig(config, getPackerConfiguration()) 742 if err == nil { 743 t.Fatal("expected config to reject missing custom data file") 744 } 745 } 746 747 func TestConfigShouldAcceptPlatformManagedImageBuild(t *testing.T) { 748 config := map[string]interface{}{ 749 "image_offer": "ignore", 750 "image_publisher": "ignore", 751 "image_sku": "ignore", 752 "location": "ignore", 753 "subscription_id": "ignore", 754 "communicator": "none", 755 "managed_image_resource_group_name": "ignore", 756 "managed_image_name": "ignore", 757 758 // Does not matter for this test case, just pick one. 759 "os_type": constants.Target_Linux, 760 } 761 762 _, _, err := newConfig(config, getPackerConfiguration()) 763 if err != nil { 764 t.Fatal("expected config to accept platform managed image build") 765 } 766 } 767 768 // If the user specified a build for a VHD and a Managed Image it should be rejected. 769 func TestConfigShouldRejectVhdAndManagedImageOutput(t *testing.T) { 770 config := map[string]interface{}{ 771 "image_offer": "ignore", 772 "image_publisher": "ignore", 773 "image_sku": "ignore", 774 "location": "ignore", 775 "subscription_id": "ignore", 776 "communicator": "none", 777 "capture_container_name": "ignore", 778 "capture_name_prefix": "ignore", 779 "managed_image_resource_group_name": "ignore", 780 "managed_image_name": "ignore", 781 782 // Does not matter for this test case, just pick one. 783 "os_type": constants.Target_Linux, 784 } 785 786 _, _, err := newConfig(config, getPackerConfiguration()) 787 if err == nil { 788 t.Fatal("expected config to reject VHD and Managed Image build") 789 } 790 } 791 792 // If the user specified a build of a VHD, but started with a managed image it should be rejected. 793 func TestConfigShouldRejectManagedImageSourceAndVhdOutput(t *testing.T) { 794 config := map[string]interface{}{ 795 "image_url": "ignore", 796 "location": "ignore", 797 "subscription_id": "ignore", 798 "communicator": "none", 799 "managed_image_resource_group_name": "ignore", 800 "managed_image_name": "ignore", 801 802 // Does not matter for this test case, just pick one. 803 "os_type": constants.Target_Linux, 804 } 805 806 _, _, err := newConfig(config, getPackerConfiguration()) 807 if err == nil { 808 t.Fatal("expected config to reject VHD and Managed Image build") 809 } 810 } 811 812 func TestConfigShouldRejectCustomAndPlatformManagedImageBuild(t *testing.T) { 813 config := map[string]interface{}{ 814 "custom_managed_image_resource_group_name": "ignore", 815 "custom_managed_image_name": "ignore", 816 "image_offer": "ignore", 817 "image_publisher": "ignore", 818 "image_sku": "ignore", 819 "location": "ignore", 820 "subscription_id": "ignore", 821 "communicator": "none", 822 "managed_image_resource_group_name": "ignore", 823 "managed_image_name": "ignore", 824 825 // Does not matter for this test case, just pick one. 826 "os_type": constants.Target_Linux, 827 } 828 829 _, _, err := newConfig(config, getPackerConfiguration()) 830 if err == nil { 831 t.Fatal("expected config to reject custom and platform input for a managed image build") 832 } 833 } 834 835 func TestConfigShouldRejectCustomAndImageUrlForManagedImageBuild(t *testing.T) { 836 config := map[string]interface{}{ 837 "image_url": "ignore", 838 "custom_managed_image_resource_group_name": "ignore", 839 "custom_managed_image_name": "ignore", 840 "location": "ignore", 841 "subscription_id": "ignore", 842 "communicator": "none", 843 "managed_image_resource_group_name": "ignore", 844 "managed_image_name": "ignore", 845 846 // Does not matter for this test case, just pick one. 847 "os_type": constants.Target_Linux, 848 } 849 850 _, _, err := newConfig(config, getPackerConfiguration()) 851 if err == nil { 852 t.Fatal("expected config to reject custom and platform input for a managed image build") 853 } 854 } 855 856 func TestConfigShouldRejectMalformedManageImageStorageAccountTypes(t *testing.T) { 857 config := map[string]interface{}{ 858 "custom_managed_image_resource_group_name": "ignore", 859 "custom_managed_image_name": "ignore", 860 "location": "ignore", 861 "subscription_id": "ignore", 862 "communicator": "none", 863 "managed_image_resource_group_name": "ignore", 864 "managed_image_name": "ignore", 865 "managed_image_storage_account_type": "--invalid--", 866 867 // Does not matter for this test case, just pick one. 868 "os_type": constants.Target_Linux, 869 } 870 871 _, _, err := newConfig(config, getPackerConfiguration()) 872 if err == nil { 873 t.Fatal("expected config to reject custom and platform input for a managed image build") 874 } 875 } 876 877 func TestConfigShouldAcceptManagedImageStorageAccountTypes(t *testing.T) { 878 config := map[string]interface{}{ 879 "custom_managed_image_resource_group_name": "ignore", 880 "custom_managed_image_name": "ignore", 881 "location": "ignore", 882 "subscription_id": "ignore", 883 "communicator": "none", 884 "managed_image_resource_group_name": "ignore", 885 "managed_image_name": "ignore", 886 887 // Does not matter for this test case, just pick one. 888 "os_type": constants.Target_Linux, 889 } 890 891 storage_account_types := []string{"Premium_LRS", "Standard_LRS"} 892 893 for _, x := range storage_account_types { 894 config["managed_image_storage_account_type"] = x 895 _, _, err := newConfig(config, getPackerConfiguration()) 896 if err != nil { 897 t.Fatalf("expected config to accept a managed_image_storage_account_type of %q", x) 898 } 899 } 900 } 901 902 func getArmBuilderConfiguration() map[string]string { 903 m := make(map[string]string) 904 for _, v := range requiredConfigValues { 905 m[v] = "ignored00" 906 } 907 908 m["communicator"] = "none" 909 m["os_type"] = constants.Target_Linux 910 return m 911 } 912 913 func getArmBuilderConfigurationWithWindows() map[string]string { 914 m := make(map[string]string) 915 for _, v := range requiredConfigValues { 916 m[v] = "ignored00" 917 } 918 919 m["object_id"] = "ignored00" 920 m["tenant_id"] = "ignored00" 921 m["winrm_username"] = "ignored00" 922 m["communicator"] = "winrm" 923 m["os_type"] = constants.Target_Windows 924 return m 925 } 926 927 func getPackerConfiguration() interface{} { 928 config := map[string]interface{}{ 929 "packer_build_name": "azure-arm-vm", 930 "packer_builder_type": "azure-arm-vm", 931 "packer_debug": "false", 932 "packer_force": "false", 933 "packer_template_path": "/home/jenkins/azure-arm-vm/template.json", 934 } 935 936 return config 937 } 938 939 func getPackerCommunicatorConfiguration() map[string]string { 940 config := map[string]string{ 941 "ssh_timeout": "1h", 942 "winrm_timeout": "2h", 943 } 944 945 return config 946 }