github.com/kikitux/packer@v0.10.1-0.20160322154024-6237df566f9f/builder/azure/arm/builder.go (about) 1 // Copyright (c) Microsoft Corporation. All rights reserved. 2 // Licensed under the MIT License. See the LICENSE file in builder/azure for license information. 3 4 package arm 5 6 import ( 7 "errors" 8 "fmt" 9 "log" 10 11 "github.com/mitchellh/packer/builder/azure/common/constants" 12 "github.com/mitchellh/packer/builder/azure/common/lin" 13 14 "github.com/Azure/go-autorest/autorest/azure" 15 16 "github.com/mitchellh/multistep" 17 "github.com/mitchellh/packer/common" 18 "github.com/mitchellh/packer/helper/communicator" 19 "github.com/mitchellh/packer/packer" 20 ) 21 22 type Builder struct { 23 config *Config 24 stateBag multistep.StateBag 25 runner multistep.Runner 26 } 27 28 const ( 29 DefaultPublicIPAddressName = "packerPublicIP" 30 ) 31 32 func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { 33 c, warnings, errs := newConfig(raws...) 34 if errs != nil { 35 return warnings, errs 36 } 37 38 b.config = c 39 40 b.stateBag = new(multistep.BasicStateBag) 41 err := b.configureStateBag(b.stateBag) 42 if err != nil { 43 return nil, err 44 } 45 46 return warnings, errs 47 } 48 49 func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { 50 ui.Say("Preparing builder ...") 51 52 b.stateBag.Put("hook", hook) 53 b.stateBag.Put(constants.Ui, ui) 54 55 servicePrincipalToken, err := b.createServicePrincipalToken() 56 if err != nil { 57 return nil, err 58 } 59 60 ui.Message("Creating Azure Resource Manager (ARM) client ...") 61 azureClient, err := NewAzureClient(b.config.SubscriptionID, b.config.ResourceGroupName, b.config.StorageAccount, servicePrincipalToken) 62 if err != nil { 63 return nil, err 64 } 65 66 steps := []multistep.Step{ 67 NewStepCreateResourceGroup(azureClient, ui), 68 NewStepValidateTemplate(azureClient, ui), 69 NewStepDeployTemplate(azureClient, ui), 70 NewStepGetIPAddress(azureClient, ui), 71 &communicator.StepConnectSSH{ 72 Config: &b.config.Comm, 73 Host: lin.SSHHost, 74 SSHConfig: lin.SSHConfig(b.config.UserName), 75 }, 76 &common.StepProvision{}, 77 NewStepGetOSDisk(azureClient, ui), 78 NewStepPowerOffCompute(azureClient, ui), 79 NewStepCaptureImage(azureClient, ui), 80 NewStepDeleteResourceGroup(azureClient, ui), 81 NewStepDeleteOSDisk(azureClient, ui), 82 } 83 84 if b.config.PackerDebug { 85 ui.Message(fmt.Sprintf("temp admin user: '%s'", b.config.UserName)) 86 ui.Message(fmt.Sprintf("temp admin password: '%s'", b.config.Password)) 87 } 88 89 b.runner = b.createRunner(&steps, ui) 90 b.runner.Run(b.stateBag) 91 92 // Report any errors. 93 if rawErr, ok := b.stateBag.GetOk(constants.Error); ok { 94 return nil, rawErr.(error) 95 } 96 97 // If we were interrupted or cancelled, then just exit. 98 if _, ok := b.stateBag.GetOk(multistep.StateCancelled); ok { 99 return nil, errors.New("Build was cancelled.") 100 } 101 102 if _, ok := b.stateBag.GetOk(multistep.StateHalted); ok { 103 return nil, errors.New("Build was halted.") 104 } 105 106 return &artifact{}, nil 107 } 108 109 func (b *Builder) Cancel() { 110 if b.runner != nil { 111 log.Println("Cancelling the step runner...") 112 b.runner.Cancel() 113 } 114 } 115 116 func (b *Builder) createRunner(steps *[]multistep.Step, ui packer.Ui) multistep.Runner { 117 if b.config.PackerDebug { 118 return &multistep.DebugRunner{ 119 Steps: *steps, 120 PauseFn: common.MultistepDebugFn(ui), 121 } 122 } 123 124 return &multistep.BasicRunner{ 125 Steps: *steps, 126 } 127 } 128 129 func (b *Builder) configureStateBag(stateBag multistep.StateBag) error { 130 stateBag.Put(constants.AuthorizedKey, b.config.sshAuthorizedKey) 131 stateBag.Put(constants.PrivateKey, b.config.sshPrivateKey) 132 133 stateBag.Put(constants.ArmComputeName, b.config.tmpComputeName) 134 stateBag.Put(constants.ArmDeploymentName, b.config.tmpDeploymentName) 135 stateBag.Put(constants.ArmLocation, b.config.Location) 136 stateBag.Put(constants.ArmResourceGroupName, b.config.tmpResourceGroupName) 137 stateBag.Put(constants.ArmTemplateParameters, b.config.toTemplateParameters()) 138 stateBag.Put(constants.ArmVirtualMachineCaptureParameters, b.config.toVirtualMachineCaptureParameters()) 139 140 stateBag.Put(constants.ArmPublicIPAddressName, DefaultPublicIPAddressName) 141 142 return nil 143 } 144 145 func (b *Builder) createServicePrincipalToken() (*azure.ServicePrincipalToken, error) { 146 oauthConfig, err := azure.PublicCloud.OAuthConfigForTenant(b.config.TenantID) 147 if err != nil { 148 return nil, err 149 } 150 151 spt, err := azure.NewServicePrincipalToken( 152 *oauthConfig, 153 b.config.ClientID, 154 b.config.ClientSecret, 155 azure.PublicCloud.ResourceManagerEndpoint) 156 157 return spt, err 158 }