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  }