github.phpd.cn/hashicorp/packer@v1.3.2/builder/azure/arm/step_capture_image.go (about) 1 package arm 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-04-01/compute" 8 "github.com/hashicorp/packer/builder/azure/common/constants" 9 "github.com/hashicorp/packer/helper/multistep" 10 "github.com/hashicorp/packer/packer" 11 ) 12 13 type StepCaptureImage struct { 14 client *AzureClient 15 generalizeVM func(resourceGroupName, computeName string) error 16 captureVhd func(ctx context.Context, resourceGroupName string, computeName string, parameters *compute.VirtualMachineCaptureParameters) error 17 captureManagedImage func(ctx context.Context, resourceGroupName string, computeName string, parameters *compute.Image) 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(context.TODO(), resourceGroupName, computeName) 46 if err != nil { 47 s.say(s.client.LastError.Error()) 48 } 49 return err 50 } 51 52 func (s *StepCaptureImage) captureImageFromVM(ctx context.Context, resourceGroupName string, imageName string, image *compute.Image) error { 53 f, err := s.client.ImagesClient.CreateOrUpdate(ctx, resourceGroupName, imageName, *image) 54 if err != nil { 55 s.say(s.client.LastError.Error()) 56 } 57 return f.WaitForCompletion(ctx, s.client.ImagesClient.Client) 58 } 59 60 func (s *StepCaptureImage) captureImage(ctx context.Context, resourceGroupName string, computeName string, parameters *compute.VirtualMachineCaptureParameters) error { 61 f, err := s.client.VirtualMachinesClient.Capture(ctx, resourceGroupName, computeName, *parameters) 62 if err != nil { 63 s.say(s.client.LastError.Error()) 64 } 65 return f.WaitForCompletion(ctx, s.client.VirtualMachinesClient.Client) 66 } 67 68 func (s *StepCaptureImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { 69 s.say("Capturing image ...") 70 71 var computeName = state.Get(constants.ArmComputeName).(string) 72 var location = state.Get(constants.ArmLocation).(string) 73 var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string) 74 var vmCaptureParameters = state.Get(constants.ArmVirtualMachineCaptureParameters).(*compute.VirtualMachineCaptureParameters) 75 var imageParameters = state.Get(constants.ArmImageParameters).(*compute.Image) 76 77 var isManagedImage = state.Get(constants.ArmIsManagedImage).(bool) 78 var targetManagedImageResourceGroupName = state.Get(constants.ArmManagedImageResourceGroupName).(string) 79 var targetManagedImageName = state.Get(constants.ArmManagedImageName).(string) 80 var targetManagedImageLocation = state.Get(constants.ArmManagedImageLocation).(string) 81 82 s.say(fmt.Sprintf(" -> Compute ResourceGroupName : '%s'", resourceGroupName)) 83 s.say(fmt.Sprintf(" -> Compute Name : '%s'", computeName)) 84 s.say(fmt.Sprintf(" -> Compute Location : '%s'", location)) 85 86 err := s.generalizeVM(resourceGroupName, computeName) 87 88 if err == nil { 89 if isManagedImage { 90 s.say(fmt.Sprintf(" -> Image ResourceGroupName : '%s'", targetManagedImageResourceGroupName)) 91 s.say(fmt.Sprintf(" -> Image Name : '%s'", targetManagedImageName)) 92 s.say(fmt.Sprintf(" -> Image Location : '%s'", targetManagedImageLocation)) 93 err = s.captureManagedImage(ctx, targetManagedImageResourceGroupName, targetManagedImageName, imageParameters) 94 } else { 95 err = s.captureVhd(ctx, resourceGroupName, computeName, vmCaptureParameters) 96 } 97 } 98 if err != nil { 99 state.Put(constants.Error, err) 100 s.error(err) 101 102 return multistep.ActionHalt 103 } 104 105 // HACK(chrboum): I do not like this. The capture method should be returning this value 106 // instead having to pass in another lambda. 107 // 108 // Having to resort to capturing the template via an inspector is hack, and once I can 109 // resolve that I can cleanup this code too. See the comments in azure_client.go for more 110 // details. 111 // [paulmey]: autorest.Future now has access to the last http.Response, but I'm not sure if 112 // the body is still accessible. 113 template := s.get(s.client) 114 state.Put(constants.ArmCaptureTemplate, template) 115 116 return multistep.ActionContinue 117 } 118 119 func (*StepCaptureImage) Cleanup(multistep.StateBag) { 120 }