2016-03-04 05:14:55 -05:00
// Copyright (c) Microsoft Corporation. All rights reserved.
2016-05-06 23:32:18 -04:00
// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
2016-03-04 05:14:55 -05:00
package arm
import (
"fmt"
2016-04-21 19:50:03 -04:00
"strings"
2016-03-04 05:14:55 -05:00
"testing"
"time"
2016-04-21 19:50:03 -04:00
"github.com/mitchellh/packer/builder/azure/common/constants"
"github.com/mitchellh/packer/packer"
2016-03-04 05:14:55 -05:00
)
// List of configuration parameters that are required by the ARM builder.
var requiredConfigValues = [ ] string {
"capture_name_prefix" ,
"capture_container_name" ,
"client_id" ,
"client_secret" ,
"image_offer" ,
"image_publisher" ,
"image_sku" ,
"location" ,
2016-04-21 19:50:03 -04:00
"os_type" ,
2016-03-04 05:14:55 -05:00
"storage_account" ,
2016-06-09 04:00:23 -04:00
"resource_group_name" ,
2016-03-04 05:14:55 -05:00
"subscription_id" ,
}
func TestConfigShouldProvideReasonableDefaultValues ( t * testing . T ) {
c , _ , err := newConfig ( getArmBuilderConfiguration ( ) , getPackerConfiguration ( ) )
if err != nil {
t . Errorf ( "Expected configuration creation to succeed, but it failed!\n" )
t . Fatalf ( " errors: %s\n" , err )
}
if c . UserName == "" {
t . Errorf ( "Expected 'UserName' to be populated, but it was empty!" )
}
if c . VMSize == "" {
t . Errorf ( "Expected 'VMSize' to be populated, but it was empty!" )
}
2016-04-21 19:50:03 -04:00
if c . ObjectID != "" {
t . Errorf ( "Expected 'ObjectID' to be nil, but it was '%s'!" , c . ObjectID )
2016-03-04 05:14:55 -05:00
}
2016-04-21 19:50:03 -04:00
}
2016-03-04 05:14:55 -05:00
2016-04-21 19:50:03 -04:00
func TestConfigShouldBeAbleToOverrideDefaultedValues ( t * testing . T ) {
builderValues := getArmBuilderConfiguration ( )
2016-03-04 05:14:55 -05:00
builderValues [ "ssh_password" ] = "override_password"
builderValues [ "ssh_username" ] = "override_username"
builderValues [ "vm_size" ] = "override_vm_size"
2016-05-17 16:53:01 -04:00
builderValues [ "communicator" ] = "ssh"
2016-03-04 05:14:55 -05:00
2016-04-21 19:50:03 -04:00
c , _ , err := newConfig ( builderValues , getPackerConfiguration ( ) )
if err != nil {
t . Fatalf ( "newConfig failed: %s" , err )
}
2016-03-04 05:14:55 -05:00
if c . Password != "override_password" {
t . Errorf ( "Expected 'Password' to be set to 'override_password', but found '%s'!" , c . Password )
}
if c . Comm . SSHPassword != "override_password" {
t . Errorf ( "Expected 'c.Comm.SSHPassword' to be set to 'override_password', but found '%s'!" , c . Comm . SSHPassword )
}
if c . UserName != "override_username" {
t . Errorf ( "Expected 'UserName' to be set to 'override_username', but found '%s'!" , c . UserName )
}
if c . Comm . SSHUsername != "override_username" {
t . Errorf ( "Expected 'c.Comm.SSHUsername' to be set to 'override_username', but found '%s'!" , c . Comm . SSHUsername )
}
if c . VMSize != "override_vm_size" {
2016-04-21 19:50:03 -04:00
t . Errorf ( "Expected 'vm_size' to be set to 'override_vm_size', but found '%s'!" , c . VMSize )
2016-03-04 05:14:55 -05:00
}
}
func TestConfigShouldDefaultVMSizeToStandardA1 ( t * testing . T ) {
c , _ , _ := newConfig ( getArmBuilderConfiguration ( ) , getPackerConfiguration ( ) )
if c . VMSize != "Standard_A1" {
t . Errorf ( "Expected 'VMSize' to default to 'Standard_A1', but got '%s'." , c . VMSize )
}
}
2016-04-21 19:50:03 -04:00
func TestConfigShouldDefaultImageVersionToLatest ( t * testing . T ) {
c , _ , _ := newConfig ( getArmBuilderConfiguration ( ) , getPackerConfiguration ( ) )
2016-03-04 05:14:55 -05:00
2016-04-21 19:50:03 -04:00
if c . ImageVersion != "latest" {
t . Errorf ( "Expected 'ImageVersion' to default to 'latest', but got '%s'." , c . ImageVersion )
}
}
2016-05-21 02:01:16 -04:00
func TestConfigShouldNotDefaultImageVersionIfCustomImage ( t * testing . T ) {
config := map [ string ] string {
"capture_name_prefix" : "ignore" ,
"capture_container_name" : "ignore" ,
"location" : "ignore" ,
"image_url" : "ignore" ,
"storage_account" : "ignore" ,
2016-06-09 13:03:31 -04:00
"resource_group_name" : "ignore" ,
2016-05-21 02:01:16 -04:00
"subscription_id" : "ignore" ,
"os_type" : constants . Target_Linux ,
"communicator" : "none" ,
}
c , _ , _ := newConfig ( config , getPackerConfiguration ( ) )
if c . ImageVersion != "" {
t . Errorf ( "Expected 'ImageVersion' to empty, but got '%s'." , c . ImageVersion )
}
}
func TestConfigShouldRejectCustomImageAndMarketPlace ( t * testing . T ) {
config := map [ string ] string {
"capture_name_prefix" : "ignore" ,
"capture_container_name" : "ignore" ,
"location" : "ignore" ,
"image_url" : "ignore" ,
2016-06-09 13:03:31 -04:00
"resource_group_name" : "ignore" ,
2016-05-21 02:01:16 -04:00
"storage_account" : "ignore" ,
"subscription_id" : "ignore" ,
"os_type" : constants . Target_Linux ,
"communicator" : "none" ,
}
packerConfiguration := getPackerConfiguration ( )
marketPlace := [ ] string { "image_publisher" , "image_offer" , "image_sku" }
for _ , x := range marketPlace {
config [ x ] = "ignore"
_ , _ , err := newConfig ( config , packerConfiguration )
if err == nil {
t . Errorf ( "Expected Config to reject image_url and %s, but it did not" , x )
}
}
}
2016-04-21 19:50:03 -04:00
func TestConfigShouldDefaultToPublicCloud ( t * testing . T ) {
c , _ , _ := newConfig ( getArmBuilderConfiguration ( ) , getPackerConfiguration ( ) )
if c . CloudEnvironmentName != "Public" {
t . Errorf ( "Expected 'CloudEnvironmentName' to default to 'Public', but got '%s'." , c . CloudEnvironmentName )
}
if c . cloudEnvironment == nil || c . cloudEnvironment . Name != "AzurePublicCloud" {
t . Errorf ( "Expected 'cloudEnvironment' to be set to 'AzurePublicCloud', but got '%s'." , c . cloudEnvironment )
}
}
func TestConfigInstantiatesCorrectAzureEnvironment ( t * testing . T ) {
config := map [ string ] string {
"capture_name_prefix" : "ignore" ,
"capture_container_name" : "ignore" ,
"image_offer" : "ignore" ,
"image_publisher" : "ignore" ,
"image_sku" : "ignore" ,
"location" : "ignore" ,
"storage_account" : "ignore" ,
2016-06-09 04:00:23 -04:00
"resource_group_name" : "ignore" ,
2016-04-21 19:50:03 -04:00
"subscription_id" : "ignore" ,
"os_type" : constants . Target_Linux ,
2016-05-17 16:53:01 -04:00
"communicator" : "none" ,
2016-04-21 19:50:03 -04:00
}
// user input is fun :)
var table = [ ] struct {
name string
environmentName string
} {
{ "China" , "AzureChinaCloud" } ,
{ "ChinaCloud" , "AzureChinaCloud" } ,
{ "AzureChinaCloud" , "AzureChinaCloud" } ,
{ "aZuReChInAcLoUd" , "AzureChinaCloud" } ,
{ "USGovernment" , "AzureUSGovernmentCloud" } ,
{ "USGovernmentCloud" , "AzureUSGovernmentCloud" } ,
{ "AzureUSGovernmentCloud" , "AzureUSGovernmentCloud" } ,
{ "aZuReUsGoVeRnMeNtClOuD" , "AzureUSGovernmentCloud" } ,
{ "Public" , "AzurePublicCloud" } ,
{ "PublicCloud" , "AzurePublicCloud" } ,
{ "AzurePublicCloud" , "AzurePublicCloud" } ,
{ "aZuRePuBlIcClOuD" , "AzurePublicCloud" } ,
}
packerConfiguration := getPackerConfiguration ( )
for _ , x := range table {
config [ "cloud_environment_name" ] = x . name
2016-06-09 04:00:23 -04:00
c , _ , err := newConfig ( config , packerConfiguration )
if err != nil {
t . Fatal ( err )
}
2016-04-21 19:50:03 -04:00
if c . cloudEnvironment == nil || c . cloudEnvironment . Name != x . environmentName {
t . Errorf ( "Expected 'cloudEnvironment' to be set to '%s', but got '%s'." , x . environmentName , c . cloudEnvironment )
}
2016-03-04 05:14:55 -05:00
}
2016-04-21 19:50:03 -04:00
}
func TestUserShouldProvideRequiredValues ( t * testing . T ) {
builderValues := getArmBuilderConfiguration ( )
2016-03-04 05:14:55 -05:00
// Ensure we can successfully create a config.
2016-04-21 19:50:03 -04:00
_ , _ , err := newConfig ( builderValues , getPackerConfiguration ( ) )
2016-03-04 05:14:55 -05:00
if err != nil {
t . Errorf ( "Expected configuration creation to succeed, but it failed!\n" )
t . Fatalf ( " -> %+v\n" , builderValues )
}
// Take away a required element, and ensure construction fails.
for _ , v := range requiredConfigValues {
2016-04-21 19:50:03 -04:00
originalValue := builderValues [ v ]
2016-03-04 05:14:55 -05:00
delete ( builderValues , v )
2016-04-21 19:50:03 -04:00
_ , _ , err := newConfig ( builderValues , getPackerConfiguration ( ) )
2016-03-04 05:14:55 -05:00
if err == nil {
t . Errorf ( "Expected configuration creation to fail, but it succeeded!\n" )
t . Fatalf ( " -> %+v\n" , builderValues )
}
2016-04-21 19:50:03 -04:00
builderValues [ v ] = originalValue
2016-03-04 05:14:55 -05:00
}
}
func TestSystemShouldDefineRuntimeValues ( t * testing . T ) {
c , _ , _ := newConfig ( getArmBuilderConfiguration ( ) , getPackerConfiguration ( ) )
if c . Password == "" {
t . Errorf ( "Expected Password to not be empty, but it was '%s'!" , c . Password )
}
if c . tmpComputeName == "" {
t . Errorf ( "Expected tmpComputeName to not be empty, but it was '%s'!" , c . tmpComputeName )
}
if c . tmpDeploymentName == "" {
t . Errorf ( "Expected tmpDeploymentName to not be empty, but it was '%s'!" , c . tmpDeploymentName )
}
if c . tmpResourceGroupName == "" {
t . Errorf ( "Expected tmpResourceGroupName to not be empty, but it was '%s'!" , c . tmpResourceGroupName )
}
if c . tmpOSDiskName == "" {
t . Errorf ( "Expected tmpOSDiskName to not be empty, but it was '%s'!" , c . tmpOSDiskName )
}
}
func TestConfigShouldTransformToVirtualMachineCaptureParameters ( t * testing . T ) {
c , _ , _ := newConfig ( getArmBuilderConfiguration ( ) , getPackerConfiguration ( ) )
parameters := c . toVirtualMachineCaptureParameters ( )
if * parameters . DestinationContainerName != c . CaptureContainerName {
t . Errorf ( "Expected DestinationContainerName to be equal to config's CaptureContainerName, but they were '%s' and '%s' respectively." , * parameters . DestinationContainerName , c . CaptureContainerName )
}
if * parameters . VhdPrefix != c . CaptureNamePrefix {
t . Errorf ( "Expected DestinationContainerName to be equal to config's CaptureContainerName, but they were '%s' and '%s' respectively." , * parameters . VhdPrefix , c . CaptureNamePrefix )
}
if * parameters . OverwriteVhds != false {
t . Error ( "Expected OverwriteVhds to be false, but it was not." )
}
}
func TestConfigShouldSupportPackersConfigElements ( t * testing . T ) {
c , _ , err := newConfig (
getArmBuilderConfiguration ( ) ,
getPackerConfiguration ( ) ,
getPackerCommunicatorConfiguration ( ) )
if err != nil {
t . Fatal ( err )
}
if c . Comm . SSHTimeout != 1 * time . Hour {
t . Errorf ( "Expected Comm.SSHTimeout to be a duration of an hour, but got '%s' instead." , c . Comm . SSHTimeout )
}
if c . Comm . WinRMTimeout != 2 * time . Hour {
t . Errorf ( "Expected Comm.WinRMTimeout to be a durationof two hours, but got '%s' instead." , c . Comm . WinRMTimeout )
}
}
2016-05-17 16:53:01 -04:00
func TestWinRMConfigShouldSetRoundTripDecorator ( t * testing . T ) {
config := getArmBuilderConfiguration ( )
config [ "communicator" ] = "winrm"
config [ "winrm_username" ] = "username"
config [ "winrm_password" ] = "password"
c , _ , err := newConfig ( config , getPackerConfiguration ( ) )
if err != nil {
t . Fatal ( err )
}
if c . Comm . WinRMTransportDecorator == nil {
t . Errorf ( "Expected WinRMTransportDecorator to be set, but it was nil" )
}
}
2016-04-21 19:50:03 -04:00
func TestUserDeviceLoginIsEnabledForLinux ( t * testing . T ) {
config := map [ string ] string {
"capture_name_prefix" : "ignore" ,
"capture_container_name" : "ignore" ,
"image_offer" : "ignore" ,
"image_publisher" : "ignore" ,
"image_sku" : "ignore" ,
"location" : "ignore" ,
"storage_account" : "ignore" ,
2016-06-09 04:00:23 -04:00
"resource_group_name" : "ignore" ,
2016-04-21 19:50:03 -04:00
"subscription_id" : "ignore" ,
"os_type" : constants . Target_Linux ,
2016-05-17 16:53:01 -04:00
"communicator" : "none" ,
2016-03-04 05:14:55 -05:00
}
2016-04-21 19:50:03 -04:00
_ , _ , err := newConfig ( config , getPackerConfiguration ( ) )
if err != nil {
t . Fatalf ( "failed to use device login for Linux: %s" , err )
}
2016-03-04 05:14:55 -05:00
}
2016-04-21 19:50:03 -04:00
func TestUseDeviceLoginIsDisabledForWindows ( t * testing . T ) {
config := map [ string ] string {
"capture_name_prefix" : "ignore" ,
"capture_container_name" : "ignore" ,
"image_offer" : "ignore" ,
"image_publisher" : "ignore" ,
"image_sku" : "ignore" ,
"location" : "ignore" ,
"storage_account" : "ignore" ,
2016-06-09 04:00:23 -04:00
"resource_group_name" : "ignore" ,
2016-04-21 19:50:03 -04:00
"subscription_id" : "ignore" ,
"os_type" : constants . Target_Windows ,
2016-05-17 16:53:01 -04:00
"communicator" : "none" ,
2016-04-21 19:50:03 -04:00
}
2016-03-04 05:14:55 -05:00
2016-04-21 19:50:03 -04:00
_ , _ , err := newConfig ( config , getPackerConfiguration ( ) )
if err == nil {
t . Fatalf ( "Expected test to fail, but it succeeded" )
2016-03-04 05:14:55 -05:00
}
2016-04-21 19:50:03 -04:00
multiError , _ := err . ( * packer . MultiError )
2016-06-22 19:04:13 -04:00
if len ( multiError . Errors ) != 2 {
t . Errorf ( "Expected to find 2 errors, but found %d errors" , len ( multiError . Errors ) )
2016-04-21 19:50:03 -04:00
}
2016-03-04 05:14:55 -05:00
2016-04-21 19:50:03 -04:00
if ! strings . Contains ( err . Error ( ) , "client_id must be specified" ) {
t . Errorf ( "Expected to find error for 'client_id must be specified" )
}
if ! strings . Contains ( err . Error ( ) , "client_secret must be specified" ) {
t . Errorf ( "Expected to find error for 'client_secret must be specified" )
}
}
2016-03-04 05:14:55 -05:00
2016-05-18 20:25:57 -04:00
func TestConfigShouldRejectMalformedCaptureNamePrefix ( t * testing . T ) {
config := map [ string ] string {
"capture_container_name" : "ignore" ,
"image_offer" : "ignore" ,
"image_publisher" : "ignore" ,
"image_sku" : "ignore" ,
"location" : "ignore" ,
"storage_account" : "ignore" ,
2016-06-09 04:00:23 -04:00
"resource_group_name" : "ignore" ,
2016-05-18 20:25:57 -04:00
"subscription_id" : "ignore" ,
2016-07-06 14:06:52 -04:00
"communicator" : "none" ,
2016-05-18 20:25:57 -04:00
// Does not matter for this test case, just pick one.
"os_type" : constants . Target_Linux ,
}
wellFormedCaptureNamePrefix := [ ] string {
"packer" ,
"AbcdefghijklmnopqrstuvwX" ,
"hypen-hypen" ,
"0leading-number" ,
"v1.core.local" ,
}
for _ , x := range wellFormedCaptureNamePrefix {
config [ "capture_name_prefix" ] = x
_ , _ , err := newConfig ( config , getPackerConfiguration ( ) )
if err != nil {
t . Errorf ( "Expected test to pass, but it failed with the well-formed capture_name_prefix set to %q." , x )
}
}
malformedCaptureNamePrefix := [ ] string {
"-leading-hypen" ,
"trailing-hypen-" ,
"trailing-period." ,
"_leading-underscore" ,
"punc-!@#$%^&*()_+-=-punc" ,
"There-are-too-many-characters-in-the-name-and-the-limit-is-twenty-four" ,
}
for _ , x := range malformedCaptureNamePrefix {
config [ "capture_name_prefix" ] = x
_ , _ , err := newConfig ( config , getPackerConfiguration ( ) )
if err == nil {
t . Errorf ( "Expected test to fail, but it succeeded with the malformed capture_name_prefix set to %q." , x )
}
}
}
func TestConfigShouldRejectMalformedCaptureContainerName ( t * testing . T ) {
config := map [ string ] string {
"capture_name_prefix" : "ignore" ,
"image_offer" : "ignore" ,
"image_publisher" : "ignore" ,
"image_sku" : "ignore" ,
"location" : "ignore" ,
"storage_account" : "ignore" ,
2016-06-09 04:00:23 -04:00
"resource_group_name" : "ignore" ,
2016-05-18 20:25:57 -04:00
"subscription_id" : "ignore" ,
2016-07-06 14:06:52 -04:00
"communicator" : "none" ,
2016-05-18 20:25:57 -04:00
// Does not matter for this test case, just pick one.
"os_type" : constants . Target_Linux ,
}
wellFormedCaptureContainerName := [ ] string {
"0leading" ,
"aleading" ,
"hype-hypen" ,
"abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz" , // 63 characters
}
for _ , x := range wellFormedCaptureContainerName {
config [ "capture_container_name" ] = x
_ , _ , err := newConfig ( config , getPackerConfiguration ( ) )
if err != nil {
t . Errorf ( "Expected test to pass, but it failed with the well-formed capture_container_name set to %q." , x )
}
}
malformedCaptureContainerName := [ ] string {
"No-Capitals" ,
"double--hypens" ,
"-leading-hypen" ,
"trailing-hypen-" ,
"punc-!@#$%^&*()_+-=-punc" ,
"there-are-over-63-characters-in-this-string-and-that-is-a-bad-container-name" ,
}
for _ , x := range malformedCaptureContainerName {
config [ "capture_container_name" ] = x
_ , _ , err := newConfig ( config , getPackerConfiguration ( ) )
if err == nil {
t . Errorf ( "Expected test to fail, but it succeeded with the malformed capture_container_name set to %q." , x )
}
}
}
2016-04-21 19:50:03 -04:00
func getArmBuilderConfiguration ( ) map [ string ] string {
m := make ( map [ string ] string )
for _ , v := range requiredConfigValues {
2016-05-18 20:25:57 -04:00
m [ v ] = fmt . Sprintf ( "ignored00" )
2016-04-21 19:50:03 -04:00
}
2016-05-17 16:53:01 -04:00
m [ "communicator" ] = "none"
2016-04-21 19:50:03 -04:00
m [ "os_type" ] = constants . Target_Linux
return m
2016-03-04 05:14:55 -05:00
}
2016-05-21 02:01:16 -04:00
func getArmBuilderConfigurationWithWindows ( ) map [ string ] string {
m := make ( map [ string ] string )
for _ , v := range requiredConfigValues {
m [ v ] = fmt . Sprintf ( "ignored00" )
}
m [ "object_id" ] = "ignored00"
m [ "tenant_id" ] = "ignored00"
m [ "winrm_username" ] = "ignored00"
m [ "communicator" ] = "winrm"
m [ "os_type" ] = constants . Target_Windows
return m
}
2016-03-04 05:14:55 -05:00
func getPackerConfiguration ( ) interface { } {
2016-05-18 20:25:57 -04:00
config := map [ string ] interface { } {
2016-06-09 04:00:23 -04:00
"packer_build_name" : "azure-arm-vm" ,
"packer_builder_type" : "azure-arm-vm" ,
"packer_debug" : "false" ,
"packer_force" : "false" ,
2016-05-18 20:25:57 -04:00
"packer_template_path" : "/home/jenkins/azure-arm-vm/template.json" ,
}
2016-03-04 05:14:55 -05:00
return config
}
2016-04-21 19:50:03 -04:00
func getPackerCommunicatorConfiguration ( ) map [ string ] string {
config := map [ string ] string {
"ssh_timeout" : "1h" ,
"winrm_timeout" : "2h" ,
}
2016-03-04 05:14:55 -05:00
return config
}