github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/builder/azure/arm/step_capture_image.go (about) 1 package arm 2 3 import ( 4 "fmt" 5 6 "github.com/Azure/azure-sdk-for-go/arm/compute" 7 "github.com/hashicorp/packer/builder/azure/common" 8 "github.com/hashicorp/packer/builder/azure/common/constants" 9 "github.com/hashicorp/packer/packer" 10 "github.com/mitchellh/multistep" 11 ) 12 13 type StepCaptureImage struct { 14 client *AzureClient 15 generalizeVM func(resourceGroupName, computeName string) error 16 captureVhd func(resourceGroupName string, computeName string, parameters *compute.VirtualMachineCaptureParameters, cancelCh <-chan struct{}) error 17 captureManagedImage func(resourceGroupName string, computeName string, parameters *compute.Image, cancelCh <-chan struct{}) error 18 get func(client *AzureClient) *CaptureTemplate 19 say func(message string) 20 error func(e error) 21 } 22 23 func NewStepCaptureImage(client *AzureClient, ui packer.Ui) *StepCaptureImage { 24 var step = &StepCaptureImage{ 25 client: client, 26 get: func(client *AzureClient) *CaptureTemplate { 27 return client.Template 28 }, 29 say: func(message string) { 30 ui.Say(message) 31 }, 32 error: func(e error) { 33 ui.Error(e.Error()) 34 }, 35 } 36 37 step.generalizeVM = step.generalize 38 step.captureVhd = step.captureImage 39 step.captureManagedImage = step.captureImageFromVM 40 41 return step 42 } 43 44 func (s *StepCaptureImage) generalize(resourceGroupName string, computeName string) error { 45 _, err := s.client.Generalize(resourceGroupName, computeName) 46 if err != nil { 47 s.say(s.client.LastError.Error()) 48 } 49 return err 50 } 51 52 func (s *StepCaptureImage) captureImageFromVM(resourceGroupName string, imageName string, image *compute.Image, cancelCh <-chan struct{}) error { 53 _, errChan := s.client.ImagesClient.CreateOrUpdate(resourceGroupName, imageName, *image, cancelCh) 54 err := <-errChan 55 if err != nil { 56 s.say(s.client.LastError.Error()) 57 } 58 return <-errChan 59 } 60 61 func (s *StepCaptureImage) captureImage(resourceGroupName string, computeName string, parameters *compute.VirtualMachineCaptureParameters, cancelCh <-chan struct{}) error { 62 _, errChan := s.client.Capture(resourceGroupName, computeName, *parameters, cancelCh) 63 err := <-errChan 64 if err != nil { 65 s.say(s.client.LastError.Error()) 66 } 67 return <-errChan 68 } 69 70 func (s *StepCaptureImage) Run(state multistep.StateBag) multistep.StepAction { 71 s.say("Capturing image ...") 72 73 var computeName = state.Get(constants.ArmComputeName).(string) 74 var location = state.Get(constants.ArmLocation).(string) 75 var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string) 76 var vmCaptureParameters = state.Get(constants.ArmVirtualMachineCaptureParameters).(*compute.VirtualMachineCaptureParameters) 77 var imageParameters = state.Get(constants.ArmImageParameters).(*compute.Image) 78 79 var isManagedImage = state.Get(constants.ArmIsManagedImage).(bool) 80 var targetManagedImageResourceGroupName = state.Get(constants.ArmManagedImageResourceGroupName).(string) 81 var targetManagedImageName = state.Get(constants.ArmManagedImageName).(string) 82 var targetManagedImageLocation = state.Get(constants.ArmManagedImageLocation).(string) 83 84 s.say(fmt.Sprintf(" -> Compute ResourceGroupName : '%s'", resourceGroupName)) 85 s.say(fmt.Sprintf(" -> Compute Name : '%s'", computeName)) 86 s.say(fmt.Sprintf(" -> Compute Location : '%s'", location)) 87 88 result := common.StartInterruptibleTask( 89 func() bool { 90 return common.IsStateCancelled(state) 91 }, 92 func(cancelCh <-chan struct{}) error { 93 err := s.generalizeVM(resourceGroupName, computeName) 94 if err != nil { 95 return err 96 } 97 98 if isManagedImage { 99 s.say(fmt.Sprintf(" -> Image ResourceGroupName : '%s'", targetManagedImageResourceGroupName)) 100 s.say(fmt.Sprintf(" -> Image Name : '%s'", targetManagedImageName)) 101 s.say(fmt.Sprintf(" -> Image Location : '%s'", targetManagedImageLocation)) 102 return s.captureManagedImage(targetManagedImageResourceGroupName, targetManagedImageName, imageParameters, cancelCh) 103 } else { 104 return s.captureVhd(resourceGroupName, computeName, vmCaptureParameters, cancelCh) 105 } 106 }) 107 108 // HACK(chrboum): I do not like this. The capture method should be returning this value 109 // instead having to pass in another lambda. I'm in this pickle because I am using 110 // common.StartInterruptibleTask which is not parametric, and only returns a type of error. 111 // I could change it to interface{}, but I do not like that solution either. 112 // 113 // Having to resort to capturing the template via an inspector is hack, and once I can 114 // resolve that I can cleanup this code too. See the comments in azure_client.go for more 115 // details. 116 template := s.get(s.client) 117 state.Put(constants.ArmCaptureTemplate, template) 118 119 return processInterruptibleResult(result, s.error, state) 120 } 121 122 func (*StepCaptureImage) Cleanup(multistep.StateBag) { 123 }