Support for building from custom managed images
This commit is contained in:
parent
8cea6f5be5
commit
c6ff4aae59
|
@ -4,8 +4,8 @@
|
|||
package arm
|
||||
|
||||
import (
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
)
|
||||
|
||||
type Authenticate struct {
|
||||
|
|
|
@ -18,10 +18,10 @@ import (
|
|||
armStorage "github.com/Azure/azure-sdk-for-go/arm/storage"
|
||||
"github.com/Azure/azure-sdk-for-go/storage"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/hashicorp/packer/builder/azure/common"
|
||||
"github.com/hashicorp/packer/version"
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -40,6 +40,7 @@ type AzureClient struct {
|
|||
network.InterfacesClient
|
||||
network.SubnetsClient
|
||||
network.VirtualNetworksClient
|
||||
compute.ImagesClient
|
||||
compute.VirtualMachinesClient
|
||||
common.VaultClient
|
||||
armStorage.AccountsClient
|
||||
|
@ -126,6 +127,12 @@ func NewAzureClient(subscriptionID, resourceGroupName, storageAccountName string
|
|||
azureClient.GroupsClient.ResponseInspector = byInspecting(maxlen)
|
||||
azureClient.GroupsClient.UserAgent += packerUserAgent
|
||||
|
||||
azureClient.ImagesClient = compute.NewImagesClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
|
||||
azureClient.ImagesClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
|
||||
azureClient.ImagesClient.RequestInspector = withInspection(maxlen)
|
||||
azureClient.ImagesClient.ResponseInspector = byInspecting(maxlen)
|
||||
azureClient.ImagesClient.UserAgent += packerUserAgent
|
||||
|
||||
azureClient.InterfacesClient = network.NewInterfacesClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
|
||||
azureClient.InterfacesClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
|
||||
azureClient.InterfacesClient.RequestInspector = withInspection(maxlen)
|
||||
|
|
|
@ -15,11 +15,12 @@ import (
|
|||
"github.com/hashicorp/packer/builder/azure/common/constants"
|
||||
"github.com/hashicorp/packer/builder/azure/common/lin"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/arm/storage"
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
packerCommon "github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
)
|
||||
|
||||
type Builder struct {
|
||||
|
@ -47,6 +48,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
|||
b.stateBag = new(multistep.BasicStateBag)
|
||||
b.configureStateBag(b.stateBag)
|
||||
b.setTemplateParameters(b.stateBag)
|
||||
b.setImageParameters(b.stateBag)
|
||||
|
||||
return warnings, errs
|
||||
}
|
||||
|
@ -87,17 +89,39 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
return nil, err
|
||||
}
|
||||
|
||||
b.config.storageAccountBlobEndpoint, err = b.getBlobEndpoint(azureClient, b.config.ResourceGroupName, b.config.StorageAccount)
|
||||
if b.config.isManagedImage() {
|
||||
group, err := azureClient.GroupsClient.Get(b.config.TargetManagedImageResourceGroupName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Cannot locate the managed image resource group %s.", b.config.TargetManagedImageResourceGroupName)
|
||||
}
|
||||
|
||||
b.config.targetManageImageLocation = *group.Location
|
||||
|
||||
// If a managed image already exists it cannot be overwritten.
|
||||
_, err = azureClient.ImagesClient.Get(b.config.TargetManagedImageResourceGroupName, b.config.TargetManagedImageName, "")
|
||||
if err == nil {
|
||||
return nil, fmt.Errorf("A managed image named %s already exists in the resource group %s.", b.config.TargetManagedImageName, b.config.TargetManagedImageResourceGroupName)
|
||||
}
|
||||
}
|
||||
|
||||
account, err := b.getBlobAccount(azureClient, b.config.ResourceGroupName, b.config.StorageAccount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.config.storageAccountBlobEndpoint = *account.AccountProperties.PrimaryEndpoints.Blob
|
||||
|
||||
if !b.config.isManagedImage() && equalLocation(*account.Location, b.config.Location) == false {
|
||||
return nil, fmt.Errorf("The storage account is located in %s, but the build will take place in %s. The locations must be identical", *account.Location, b.config.Location)
|
||||
}
|
||||
|
||||
endpointConnectType := PublicEndpoint
|
||||
if b.isPrivateNetworkCommunication() {
|
||||
endpointConnectType = PrivateEndpoint
|
||||
}
|
||||
|
||||
b.setRuntimeParameters(b.stateBag)
|
||||
b.setTemplateParameters(b.stateBag)
|
||||
b.setImageParameters(b.stateBag)
|
||||
var steps []multistep.Step
|
||||
|
||||
if b.config.OSType == constants.Target_Linux {
|
||||
|
@ -198,13 +222,21 @@ func (b *Builder) Cancel() {
|
|||
}
|
||||
}
|
||||
|
||||
func (b *Builder) getBlobEndpoint(client *AzureClient, resourceGroupName string, storageAccountName string) (string, error) {
|
||||
func equalLocation(location1, location2 string) bool {
|
||||
return strings.EqualFold(canonicalizeLocation(location1), canonicalizeLocation(location2))
|
||||
}
|
||||
|
||||
func canonicalizeLocation(location string) string {
|
||||
return strings.Replace(location, " ", "", -1)
|
||||
}
|
||||
|
||||
func (b *Builder) getBlobAccount(client *AzureClient, resourceGroupName string, storageAccountName string) (*storage.Account, error) {
|
||||
account, err := client.AccountsClient.GetProperties(resourceGroupName, storageAccountName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return *account.AccountProperties.PrimaryEndpoints.Blob, nil
|
||||
return &account, err
|
||||
}
|
||||
|
||||
func (b *Builder) configureStateBag(stateBag multistep.StateBag) {
|
||||
|
@ -220,12 +252,25 @@ func (b *Builder) configureStateBag(stateBag multistep.StateBag) {
|
|||
stateBag.Put(constants.ArmPublicIPAddressName, DefaultPublicIPAddressName)
|
||||
stateBag.Put(constants.ArmResourceGroupName, b.config.tmpResourceGroupName)
|
||||
stateBag.Put(constants.ArmStorageAccountName, b.config.StorageAccount)
|
||||
|
||||
stateBag.Put(constants.ArmIsManagedImage, b.config.isManagedImage())
|
||||
stateBag.Put(constants.ArmTargetManagedImageResourceGroupName, b.config.TargetManagedImageResourceGroupName)
|
||||
stateBag.Put(constants.ArmTargetManagedImageName, b.config.TargetManagedImageName)
|
||||
}
|
||||
|
||||
// Parameters that are only known at runtime after querying Azure.
|
||||
func (b *Builder) setRuntimeParameters(stateBag multistep.StateBag) {
|
||||
stateBag.Put(constants.ArmTargetManagedImageLocation, b.config.targetManageImageLocation)
|
||||
}
|
||||
|
||||
func (b *Builder) setTemplateParameters(stateBag multistep.StateBag) {
|
||||
stateBag.Put(constants.ArmVirtualMachineCaptureParameters, b.config.toVirtualMachineCaptureParameters())
|
||||
}
|
||||
|
||||
func (b *Builder) setImageParameters(stateBag multistep.StateBag) {
|
||||
stateBag.Put(constants.ArmImageParameters, b.config.toImageParameters())
|
||||
}
|
||||
|
||||
func (b *Builder) getServicePrincipalTokens(say func(string)) (*adal.ServicePrincipalToken, *adal.ServicePrincipalToken, error) {
|
||||
var servicePrincipalToken *adal.ServicePrincipalToken
|
||||
var servicePrincipalTokenVault *adal.ServicePrincipalToken
|
||||
|
|
|
@ -65,8 +65,19 @@ type Config struct {
|
|||
ImageSku string `mapstructure:"image_sku"`
|
||||
ImageVersion string `mapstructure:"image_version"`
|
||||
ImageUrl string `mapstructure:"image_url"`
|
||||
Location string `mapstructure:"location"`
|
||||
VMSize string `mapstructure:"vm_size"`
|
||||
|
||||
ManagedImageResourceGroupName string `mapstructure:"managed_image_resource_group_name"`
|
||||
ManagedImageName string `mapstructure:"managed_image_name"`
|
||||
managedImageLocation string
|
||||
managedImageBlobUri string
|
||||
managedImageOSState compute.OperatingSystemStateTypes
|
||||
|
||||
Location string `mapstructure:"location"`
|
||||
VMSize string `mapstructure:"vm_size"`
|
||||
|
||||
TargetManagedImageResourceGroupName string `mapstructure:"target_managed_image_resource_group_name"`
|
||||
TargetManagedImageName string `mapstructure:"target_managed_image_name"`
|
||||
targetManageImageLocation string
|
||||
|
||||
// Deployment
|
||||
AzureTags map[string]*string `mapstructure:"azure_tags"`
|
||||
|
@ -118,6 +129,14 @@ type keyVaultCertificate struct {
|
|||
Password string `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Config) toVMID() string {
|
||||
return fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/virtualMachines/%s", c.SubscriptionID, c.tmpResourceGroupName, c.tmpComputeName)
|
||||
}
|
||||
|
||||
func (c *Config) isManagedImage() bool {
|
||||
return c.TargetManagedImageName != ""
|
||||
}
|
||||
|
||||
func (c *Config) toVirtualMachineCaptureParameters() *compute.VirtualMachineCaptureParameters {
|
||||
return &compute.VirtualMachineCaptureParameters{
|
||||
DestinationContainerName: &c.CaptureContainerName,
|
||||
|
@ -126,6 +145,18 @@ func (c *Config) toVirtualMachineCaptureParameters() *compute.VirtualMachineCapt
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Config) toImageParameters() *compute.Image {
|
||||
return &compute.Image{
|
||||
ImageProperties: &compute.ImageProperties{
|
||||
SourceVirtualMachine: &compute.SubResource{
|
||||
ID: to.StringPtr(c.toVMID()),
|
||||
},
|
||||
},
|
||||
Location: to.StringPtr(c.Location),
|
||||
Tags: &c.AzureTags,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) createCertificate() (string, error) {
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
|
@ -277,7 +308,9 @@ func setSshValues(c *Config) error {
|
|||
|
||||
func setWinRMCertificate(c *Config) error {
|
||||
c.Comm.WinRMTransportDecorator =
|
||||
func() winrm.Transporter { return &winrm.ClientNTLM{} }
|
||||
func() winrm.Transporter {
|
||||
return &winrm.ClientNTLM{}
|
||||
}
|
||||
|
||||
cert, err := c.createCertificate()
|
||||
c.winrmCertificate = cert
|
||||
|
@ -372,7 +405,7 @@ func provideDefaultValues(c *Config) {
|
|||
c.VMSize = DefaultVMSize
|
||||
}
|
||||
|
||||
if c.ImageUrl == "" && c.ImageVersion == "" {
|
||||
if c.ImagePublisher != "" && c.ImageVersion == "" {
|
||||
c.ImageVersion = DefaultImageVersion
|
||||
}
|
||||
|
||||
|
@ -467,7 +500,13 @@ func assertRequiredParametersSet(c *Config, errs *packer.MultiError) {
|
|||
|
||||
/////////////////////////////////////////////
|
||||
// Compute
|
||||
if c.ImageUrl == "" {
|
||||
if c.ImageUrl != "" &&
|
||||
(c.ManagedImageName != "" || c.ManagedImageResourceGroupName != "") &&
|
||||
(c.ImagePublisher != "" || c.ImageOffer != "" || c.ImageSku != "") {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("Specify either a VHD (image_url), Image Reference (image_publisher, image_offer, image_sku) or a Managed Disk (managed_disk_image_name, managed_disk_resource_group_name"))
|
||||
}
|
||||
|
||||
if c.ImageUrl == "" && c.ManagedImageName == "" {
|
||||
if c.ImagePublisher == "" {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("An image_publisher must be specified"))
|
||||
}
|
||||
|
@ -479,6 +518,19 @@ func assertRequiredParametersSet(c *Config, errs *packer.MultiError) {
|
|||
if c.ImageSku == "" {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("An image_sku must be specified"))
|
||||
}
|
||||
} else if c.ImageUrl == "" && c.ImagePublisher == "" {
|
||||
if c.ManagedImageName == "" {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("A managed_image_name must be specified"))
|
||||
}
|
||||
if c.ManagedImageResourceGroupName == "" {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("An managed_image_resource_group_name must be specified"))
|
||||
}
|
||||
if c.TargetManagedImageName == "" {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("An target_managed_image_name must be specified"))
|
||||
}
|
||||
if c.TargetManagedImageResourceGroupName == "" {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("An target_managed_image_resource_group_name must be specified"))
|
||||
}
|
||||
} else {
|
||||
if c.ImagePublisher != "" || c.ImageOffer != "" || c.ImageSku != "" || c.ImageVersion != "" {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("An image_url must not be specified if image_publisher, image_offer, image_sku, or image_version is specified"))
|
||||
|
|
|
@ -10,6 +10,7 @@ package arm
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Azure/azure-sdk-for-go/arm/compute"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -43,6 +44,17 @@ func (s *resourceResolver) Resolve(c *Config) error {
|
|||
c.VirtualNetworkSubnetName = subnetName
|
||||
}
|
||||
|
||||
if s.shouldResolveManagedImageName(c) {
|
||||
image, err := findManagedImageByName(s.client, c.ManagedImageName, c.ManagedImageResourceGroupName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.managedImageBlobUri = *image.ImageProperties.StorageProfile.OsDisk.BlobURI
|
||||
c.managedImageLocation = *image.Location
|
||||
c.managedImageOSState = image.ImageProperties.StorageProfile.OsDisk.OsState
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -50,12 +62,31 @@ func (s *resourceResolver) shouldResolveResourceGroup(c *Config) bool {
|
|||
return c.VirtualNetworkName != "" && c.VirtualNetworkResourceGroupName == ""
|
||||
}
|
||||
|
||||
func (s *resourceResolver) shouldResolveManagedImageName(c *Config) bool {
|
||||
return c.ManagedImageName != ""
|
||||
}
|
||||
|
||||
func getResourceGroupNameFromId(id string) string {
|
||||
// "/subscriptions/3f499422-dd76-4114-8859-86d526c9deb6/resourceGroups/packer-Resource-Group-yylnwsl30j/providers/...
|
||||
xs := strings.Split(id, "/")
|
||||
return xs[4]
|
||||
}
|
||||
|
||||
func findManagedImageByName(client *AzureClient, name, resourceGroupName string) (*compute.Image, error) {
|
||||
images, err := client.ImagesClient.ListByResourceGroup(resourceGroupName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, image := range *images.Value {
|
||||
if strings.EqualFold(name, *image.Name) {
|
||||
return &image, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Cannot find an image named '%s' in the resource group '%s'", name, resourceGroupName)
|
||||
}
|
||||
|
||||
func findVirtualNetworkResourceGroup(client *AzureClient, name string) (string, error) {
|
||||
virtualNetworks, err := client.VirtualNetworksClient.ListAll()
|
||||
if err != nil {
|
||||
|
|
|
@ -14,39 +14,49 @@ import (
|
|||
)
|
||||
|
||||
type StepCaptureImage struct {
|
||||
client *AzureClient
|
||||
capture func(resourceGroupName string, computeName string, parameters *compute.VirtualMachineCaptureParameters, cancelCh <-chan struct{}) error
|
||||
get func(client *AzureClient) *CaptureTemplate
|
||||
say func(message string)
|
||||
error func(e error)
|
||||
client *AzureClient
|
||||
generalizeVM func(resourceGroupName, computeName string) error
|
||||
captureVhd func(resourceGroupName string, computeName string, parameters *compute.VirtualMachineCaptureParameters, cancelCh <-chan struct{}) error
|
||||
captureManagedImage func(resourceGroupName string, computeName string, parameters *compute.Image, cancelCh <-chan struct{}) error
|
||||
get func(client *AzureClient) *CaptureTemplate
|
||||
say func(message string)
|
||||
error func(e error)
|
||||
}
|
||||
|
||||
func NewStepCaptureImage(client *AzureClient, ui packer.Ui) *StepCaptureImage {
|
||||
var step = &StepCaptureImage{
|
||||
client: client,
|
||||
get: func(client *AzureClient) *CaptureTemplate { return client.Template },
|
||||
say: func(message string) { ui.Say(message) },
|
||||
error: func(e error) { ui.Error(e.Error()) },
|
||||
get: func(client *AzureClient) *CaptureTemplate {
|
||||
return client.Template
|
||||
},
|
||||
say: func(message string) {
|
||||
ui.Say(message)
|
||||
},
|
||||
error: func(e error) {
|
||||
ui.Error(e.Error())
|
||||
},
|
||||
}
|
||||
|
||||
step.capture = step.captureImage
|
||||
step.generalizeVM = step.generalize
|
||||
step.captureVhd = step.captureImage
|
||||
step.captureManagedImage = step.captureImageFromVM
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepCaptureImage) captureImage(resourceGroupName string, computeName string, parameters *compute.VirtualMachineCaptureParameters, cancelCh <-chan struct{}) error {
|
||||
func (s *StepCaptureImage) generalize(resourceGroupName string, computeName string) error {
|
||||
_, err := s.client.Generalize(resourceGroupName, computeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *StepCaptureImage) captureImageFromVM(resourceGroupName string, imageName string, image *compute.Image, cancelCh <-chan struct{}) error {
|
||||
_, errChan := s.client.ImagesClient.CreateOrUpdate(resourceGroupName, imageName, *image, cancelCh)
|
||||
return <-errChan
|
||||
}
|
||||
|
||||
func (s *StepCaptureImage) captureImage(resourceGroupName string, computeName string, parameters *compute.VirtualMachineCaptureParameters, cancelCh <-chan struct{}) error {
|
||||
_, errChan := s.client.Capture(resourceGroupName, computeName, *parameters, cancelCh)
|
||||
|
||||
err = <-errChan
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return <-errChan
|
||||
}
|
||||
|
||||
func (s *StepCaptureImage) Run(state multistep.StateBag) multistep.StepAction {
|
||||
|
@ -54,15 +64,35 @@ func (s *StepCaptureImage) Run(state multistep.StateBag) multistep.StepAction {
|
|||
|
||||
var computeName = state.Get(constants.ArmComputeName).(string)
|
||||
var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string)
|
||||
var parameters = state.Get(constants.ArmVirtualMachineCaptureParameters).(*compute.VirtualMachineCaptureParameters)
|
||||
var vmCaptureParameters = state.Get(constants.ArmVirtualMachineCaptureParameters).(*compute.VirtualMachineCaptureParameters)
|
||||
var imageParameters = state.Get(constants.ArmImageParameters).(*compute.Image)
|
||||
|
||||
s.say(fmt.Sprintf(" -> ResourceGroupName : '%s'", resourceGroupName))
|
||||
s.say(fmt.Sprintf(" -> ComputeName : '%s'", computeName))
|
||||
var isManagedImage = state.Get(constants.ArmIsManagedImage).(bool)
|
||||
var targetManagedImageResourceGroupName = state.Get(constants.ArmTargetManagedImageResourceGroupName).(string)
|
||||
var targetManagedImageName = state.Get(constants.ArmTargetManagedImageName).(string)
|
||||
var targetManagedImageLocation = state.Get(constants.ArmTargetManagedImageLocation).(string)
|
||||
|
||||
s.say(fmt.Sprintf(" -> ResourceGroupName : '%s'", resourceGroupName))
|
||||
s.say(fmt.Sprintf(" -> ComputeName : '%s'", computeName))
|
||||
|
||||
result := common.StartInterruptibleTask(
|
||||
func() bool { return common.IsStateCancelled(state) },
|
||||
func() bool {
|
||||
return common.IsStateCancelled(state)
|
||||
},
|
||||
func(cancelCh <-chan struct{}) error {
|
||||
return s.capture(resourceGroupName, computeName, parameters, cancelCh)
|
||||
err := s.generalizeVM(resourceGroupName, computeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isManagedImage {
|
||||
s.say(fmt.Sprintf(" -> ImageResourceGroupName : '%s'", targetManagedImageResourceGroupName))
|
||||
s.say(fmt.Sprintf(" -> ImageName : '%s'", targetManagedImageName))
|
||||
s.say(fmt.Sprintf(" -> Image Location : '%s'", targetManagedImageLocation))
|
||||
return s.captureManagedImage(targetManagedImageResourceGroupName, targetManagedImageName, imageParameters, cancelCh)
|
||||
} else {
|
||||
return s.captureVhd(resourceGroupName, computeName, vmCaptureParameters, cancelCh)
|
||||
}
|
||||
})
|
||||
|
||||
// HACK(chrboum): I do not like this. The capture method should be returning this value
|
||||
|
|
|
@ -14,9 +14,12 @@ import (
|
|||
|
||||
func TestStepCaptureImageShouldFailIfCaptureFails(t *testing.T) {
|
||||
var testSubject = &StepCaptureImage{
|
||||
capture: func(string, string, *compute.VirtualMachineCaptureParameters, <-chan struct{}) error {
|
||||
captureVhd: func(string, string, *compute.VirtualMachineCaptureParameters, <-chan struct{}) error {
|
||||
return fmt.Errorf("!! Unit Test FAIL !!")
|
||||
},
|
||||
generalizeVM: func(string, string) error {
|
||||
return nil
|
||||
},
|
||||
get: func(client *AzureClient) *CaptureTemplate {
|
||||
return nil
|
||||
},
|
||||
|
@ -38,7 +41,10 @@ func TestStepCaptureImageShouldFailIfCaptureFails(t *testing.T) {
|
|||
|
||||
func TestStepCaptureImageShouldPassIfCapturePasses(t *testing.T) {
|
||||
var testSubject = &StepCaptureImage{
|
||||
capture: func(string, string, *compute.VirtualMachineCaptureParameters, <-chan struct{}) error { return nil },
|
||||
captureVhd: func(string, string, *compute.VirtualMachineCaptureParameters, <-chan struct{}) error { return nil },
|
||||
generalizeVM: func(string, string) error {
|
||||
return nil
|
||||
},
|
||||
get: func(client *AzureClient) *CaptureTemplate {
|
||||
return nil
|
||||
},
|
||||
|
@ -70,13 +76,16 @@ func TestStepCaptureImageShouldTakeStepArgumentsFromStateBag(t *testing.T) {
|
|||
}
|
||||
|
||||
var testSubject = &StepCaptureImage{
|
||||
capture: func(resourceGroupName string, computeName string, parameters *compute.VirtualMachineCaptureParameters, cancelCh <-chan struct{}) error {
|
||||
captureVhd: func(resourceGroupName string, computeName string, parameters *compute.VirtualMachineCaptureParameters, cancelCh <-chan struct{}) error {
|
||||
actualResourceGroupName = resourceGroupName
|
||||
actualComputeName = computeName
|
||||
actualVirtualMachineCaptureParameters = parameters
|
||||
|
||||
return nil
|
||||
},
|
||||
generalizeVM: func(string, string) error {
|
||||
return nil
|
||||
},
|
||||
get: func(client *AzureClient) *CaptureTemplate {
|
||||
return actualCaptureTemplate
|
||||
},
|
||||
|
@ -120,5 +129,11 @@ func createTestStateBagStepCaptureImage() multistep.StateBag {
|
|||
stateBag.Put(constants.ArmResourceGroupName, "Unit Test: ResourceGroupName")
|
||||
stateBag.Put(constants.ArmVirtualMachineCaptureParameters, &compute.VirtualMachineCaptureParameters{})
|
||||
|
||||
stateBag.Put(constants.ArmIsManagedImage, false)
|
||||
stateBag.Put(constants.ArmTargetManagedImageResourceGroupName, "")
|
||||
stateBag.Put(constants.ArmTargetManagedImageName, "")
|
||||
stateBag.Put(constants.ArmTargetManagedImageLocation, "")
|
||||
stateBag.Put(constants.ArmImageParameters, &compute.Image{})
|
||||
|
||||
return stateBag
|
||||
}
|
||||
|
|
|
@ -71,7 +71,9 @@ func (s *StepCreateResourceGroup) Cleanup(state multistep.StateBag) {
|
|||
ui.Say("\nCleanup requested, deleting resource group ...")
|
||||
|
||||
var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string)
|
||||
_, err := s.client.GroupsClient.Delete(resourceGroupName, nil)
|
||||
_, errChan := s.client.GroupsClient.Delete(resourceGroupName, nil)
|
||||
err := <-errChan
|
||||
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("Error deleting resource group. Please delete it manually.\n\n"+
|
||||
"Name: %s\n"+
|
||||
|
|
|
@ -41,6 +41,13 @@ func (s *StepDeleteOSDisk) Run(state multistep.StateBag) multistep.StepAction {
|
|||
s.say("Deleting the temporary OS disk ...")
|
||||
|
||||
var osDisk = state.Get(constants.ArmOSDiskVhd).(string)
|
||||
var isManagedDisk = state.Get(constants.ArmIsManagedImage).(bool)
|
||||
|
||||
if isManagedDisk {
|
||||
s.say(fmt.Sprintf(" -> OS Disk : skipping, managed disk was used..."))
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
s.say(fmt.Sprintf(" -> OS Disk : '%s'", osDisk))
|
||||
|
||||
u, err := url.Parse(osDisk)
|
||||
|
|
|
@ -108,6 +108,7 @@ func TestStepDeleteOSDiskShouldHandleComplexStorageContainerNames(t *testing.T)
|
|||
func DeleteTestStateBagStepDeleteOSDisk(osDiskVhd string) multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
stateBag.Put(constants.ArmOSDiskVhd, osDiskVhd)
|
||||
stateBag.Put(constants.ArmIsManagedImage, false)
|
||||
|
||||
return stateBag
|
||||
}
|
||||
|
|
|
@ -53,9 +53,16 @@ func (s *StepGetOSDisk) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
s.say(fmt.Sprintf(" -> OS Disk : '%s'", *vm.StorageProfile.OsDisk.Vhd.URI))
|
||||
state.Put(constants.ArmOSDiskVhd, *vm.StorageProfile.OsDisk.Vhd.URI)
|
||||
var vhdUri string
|
||||
if vm.StorageProfile.OsDisk.Vhd != nil {
|
||||
s.say(fmt.Sprintf(" -> OS Disk : '%s'", vhdUri))
|
||||
vhdUri = *vm.StorageProfile.OsDisk.Vhd.URI
|
||||
} else {
|
||||
s.say(fmt.Sprintf(" -> Managed OS Disk : '%s'", vhdUri))
|
||||
vhdUri = *vm.StorageProfile.OsDisk.ManagedDisk.ID
|
||||
}
|
||||
|
||||
state.Put(constants.ArmOSDiskVhd, vhdUri)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,10 @@ func GetVirtualMachineDeployment(config *Config) (*resources.Deployment, error)
|
|||
|
||||
if config.ImageUrl != "" {
|
||||
builder.SetImageUrl(config.ImageUrl, osType)
|
||||
} else if config.ManagedImageName != "" {
|
||||
builder.SetManagedDiskUrl(config.ManagedImageName, config.managedImageLocation, config.managedImageBlobUri, config.managedImageOSState)
|
||||
} else if config.TargetManagedImageName != "" && config.ImagePublisher != "" {
|
||||
builder.SetManagedMarketplaceImage(config.Location, config.ImagePublisher, config.ImageOffer, config.ImageSku, config.ImageVersion)
|
||||
} else {
|
||||
builder.SetMarketPlaceImage(config.ImagePublisher, config.ImageOffer, config.ImageSku, config.ImageVersion)
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('publicIPAddressApiVersion')]",
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('publicIPAddressName')]",
|
||||
"properties": {
|
||||
|
@ -38,7 +38,7 @@
|
|||
"type": "Microsoft.Network/publicIPAddresses"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('virtualNetworksApiVersion')]",
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('virtualNetworkName')]",
|
||||
"properties": {
|
||||
|
@ -59,7 +59,7 @@
|
|||
"type": "Microsoft.Network/virtualNetworks"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('networkInterfacesApiVersion')]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
|
||||
"[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
|
||||
|
@ -144,9 +144,12 @@
|
|||
],
|
||||
"variables": {
|
||||
"addressPrefix": "10.0.0.0/16",
|
||||
"apiVersion": "2015-06-15",
|
||||
"apiVersion": "2017-03-30",
|
||||
"location": "[resourceGroup().location]",
|
||||
"managedDiskApiVersion": "2017-03-30",
|
||||
"networkInterfacesApiVersion": "2017-04-01",
|
||||
"nicName": "packerNic",
|
||||
"publicIPAddressApiVersion": "2017-04-01",
|
||||
"publicIPAddressName": "packerPublicIP",
|
||||
"publicIPAddressType": "Dynamic",
|
||||
"sshKeyPath": "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]",
|
||||
|
@ -155,6 +158,7 @@
|
|||
"subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",
|
||||
"virtualNetworkName": "packerNetwork",
|
||||
"virtualNetworkResourceGroup": "[resourceGroup().name]",
|
||||
"virtualNetworksApiVersion": "2017-04-01",
|
||||
"vmStorageAccountContainerName": "images",
|
||||
"vnetID": "[resourceId(variables('virtualNetworkResourceGroup'), 'Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]"
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('publicIPAddressApiVersion')]",
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('publicIPAddressName')]",
|
||||
"properties": {
|
||||
|
@ -38,7 +38,7 @@
|
|||
"type": "Microsoft.Network/publicIPAddresses"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('virtualNetworksApiVersion')]",
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('virtualNetworkName')]",
|
||||
"properties": {
|
||||
|
@ -59,7 +59,7 @@
|
|||
"type": "Microsoft.Network/virtualNetworks"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('networkInterfacesApiVersion')]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
|
||||
"[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
|
||||
|
@ -142,9 +142,12 @@
|
|||
],
|
||||
"variables": {
|
||||
"addressPrefix": "10.0.0.0/16",
|
||||
"apiVersion": "2015-06-15",
|
||||
"apiVersion": "2017-03-30",
|
||||
"location": "[resourceGroup().location]",
|
||||
"managedDiskApiVersion": "2017-03-30",
|
||||
"networkInterfacesApiVersion": "2017-04-01",
|
||||
"nicName": "packerNic",
|
||||
"publicIPAddressApiVersion": "2017-04-01",
|
||||
"publicIPAddressName": "packerPublicIP",
|
||||
"publicIPAddressType": "Dynamic",
|
||||
"sshKeyPath": "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]",
|
||||
|
@ -153,6 +156,7 @@
|
|||
"subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",
|
||||
"virtualNetworkName": "packerNetwork",
|
||||
"virtualNetworkResourceGroup": "[resourceGroup().name]",
|
||||
"virtualNetworksApiVersion": "2017-04-01",
|
||||
"vmStorageAccountContainerName": "images",
|
||||
"vnetID": "[resourceId(variables('virtualNetworkResourceGroup'), 'Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]"
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('networkInterfacesApiVersion')]",
|
||||
"dependsOn": [],
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('nicName')]",
|
||||
|
@ -103,9 +103,12 @@
|
|||
],
|
||||
"variables": {
|
||||
"addressPrefix": "10.0.0.0/16",
|
||||
"apiVersion": "2015-06-15",
|
||||
"apiVersion": "2017-03-30",
|
||||
"location": "[resourceGroup().location]",
|
||||
"managedDiskApiVersion": "2017-03-30",
|
||||
"networkInterfacesApiVersion": "2017-04-01",
|
||||
"nicName": "packerNic",
|
||||
"publicIPAddressApiVersion": "2017-04-01",
|
||||
"publicIPAddressName": "packerPublicIP",
|
||||
"publicIPAddressType": "Dynamic",
|
||||
"sshKeyPath": "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]",
|
||||
|
@ -114,6 +117,7 @@
|
|||
"subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",
|
||||
"virtualNetworkName": "virtualNetworkName",
|
||||
"virtualNetworkResourceGroup": "virtualNetworkResourceGroupName",
|
||||
"virtualNetworksApiVersion": "2017-04-01",
|
||||
"vmStorageAccountContainerName": "images",
|
||||
"vnetID": "[resourceId(variables('virtualNetworkResourceGroup'), 'Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]"
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('publicIPAddressApiVersion')]",
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('publicIPAddressName')]",
|
||||
"properties": {
|
||||
|
@ -43,7 +43,7 @@
|
|||
"type": "Microsoft.Network/publicIPAddresses"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('virtualNetworksApiVersion')]",
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('virtualNetworkName')]",
|
||||
"properties": {
|
||||
|
@ -69,7 +69,7 @@
|
|||
"type": "Microsoft.Network/virtualNetworks"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('networkInterfacesApiVersion')]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
|
||||
"[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
|
||||
|
@ -162,9 +162,12 @@
|
|||
],
|
||||
"variables": {
|
||||
"addressPrefix": "10.0.0.0/16",
|
||||
"apiVersion": "2015-06-15",
|
||||
"apiVersion": "2017-03-30",
|
||||
"location": "[resourceGroup().location]",
|
||||
"managedDiskApiVersion": "2017-03-30",
|
||||
"networkInterfacesApiVersion": "2017-04-01",
|
||||
"nicName": "packerNic",
|
||||
"publicIPAddressApiVersion": "2017-04-01",
|
||||
"publicIPAddressName": "packerPublicIP",
|
||||
"publicIPAddressType": "Dynamic",
|
||||
"sshKeyPath": "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]",
|
||||
|
@ -173,6 +176,7 @@
|
|||
"subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",
|
||||
"virtualNetworkName": "packerNetwork",
|
||||
"virtualNetworkResourceGroup": "[resourceGroup().name]",
|
||||
"virtualNetworksApiVersion": "2017-04-01",
|
||||
"vmStorageAccountContainerName": "images",
|
||||
"vnetID": "[resourceId(variables('virtualNetworkResourceGroup'), 'Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]"
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('publicIPAddressApiVersion')]",
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('publicIPAddressName')]",
|
||||
"properties": {
|
||||
|
@ -38,7 +38,7 @@
|
|||
"type": "Microsoft.Network/publicIPAddresses"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('virtualNetworksApiVersion')]",
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('virtualNetworkName')]",
|
||||
"properties": {
|
||||
|
@ -59,7 +59,7 @@
|
|||
"type": "Microsoft.Network/virtualNetworks"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('networkInterfacesApiVersion')]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
|
||||
"[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
|
||||
|
@ -143,9 +143,12 @@
|
|||
],
|
||||
"variables": {
|
||||
"addressPrefix": "10.0.0.0/16",
|
||||
"apiVersion": "2015-06-15",
|
||||
"apiVersion": "2017-03-30",
|
||||
"location": "[resourceGroup().location]",
|
||||
"managedDiskApiVersion": "2017-03-30",
|
||||
"networkInterfacesApiVersion": "2017-04-01",
|
||||
"nicName": "packerNic",
|
||||
"publicIPAddressApiVersion": "2017-04-01",
|
||||
"publicIPAddressName": "packerPublicIP",
|
||||
"publicIPAddressType": "Dynamic",
|
||||
"sshKeyPath": "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]",
|
||||
|
@ -154,6 +157,7 @@
|
|||
"subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",
|
||||
"virtualNetworkName": "packerNetwork",
|
||||
"virtualNetworkResourceGroup": "[resourceGroup().name]",
|
||||
"virtualNetworksApiVersion": "2017-04-01",
|
||||
"vmStorageAccountContainerName": "images",
|
||||
"vnetID": "[resourceId(variables('virtualNetworkResourceGroup'), 'Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
{
|
||||
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"adminPassword": {
|
||||
"type": "string"
|
||||
},
|
||||
"adminUsername": {
|
||||
"type": "string"
|
||||
},
|
||||
"dnsNameForPublicIP": {
|
||||
"type": "string"
|
||||
},
|
||||
"osDiskName": {
|
||||
"type": "string"
|
||||
},
|
||||
"storageAccountBlobEndpoint": {
|
||||
"type": "string"
|
||||
},
|
||||
"vmName": {
|
||||
"type": "string"
|
||||
},
|
||||
"vmSize": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "[variables('publicIPAddressApiVersion')]",
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('publicIPAddressName')]",
|
||||
"properties": {
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[parameters('dnsNameForPublicIP')]"
|
||||
},
|
||||
"publicIPAllocationMethod": "[variables('publicIPAddressType')]"
|
||||
},
|
||||
"type": "Microsoft.Network/publicIPAddresses"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('virtualNetworksApiVersion')]",
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('virtualNetworkName')]",
|
||||
"properties": {
|
||||
"addressSpace": {
|
||||
"addressPrefixes": [
|
||||
"[variables('addressPrefix')]"
|
||||
]
|
||||
},
|
||||
"subnets": [
|
||||
{
|
||||
"name": "[variables('subnetName')]",
|
||||
"properties": {
|
||||
"addressPrefix": "[variables('subnetAddressPrefix')]"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "Microsoft.Network/virtualNetworks"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('networkInterfacesApiVersion')]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
|
||||
"[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
|
||||
],
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('nicName')]",
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"publicIPAddress": {
|
||||
"id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]"
|
||||
},
|
||||
"subnet": {
|
||||
"id": "[variables('subnetRef')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "Microsoft.Network/networkInterfaces"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]",
|
||||
"[concat('Microsoft.Compute/images/', 'ManagedImageName')]"
|
||||
],
|
||||
"location": "[variables('location')]",
|
||||
"name": "[parameters('vmName')]",
|
||||
"properties": {
|
||||
"diagnosticsProfile": {
|
||||
"bootDiagnostics": {
|
||||
"enabled": false
|
||||
}
|
||||
},
|
||||
"hardwareProfile": {
|
||||
"vmSize": "[parameters('vmSize')]"
|
||||
},
|
||||
"networkProfile": {
|
||||
"networkInterfaces": [
|
||||
{
|
||||
"id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
|
||||
}
|
||||
]
|
||||
},
|
||||
"osProfile": {
|
||||
"adminPassword": "[parameters('adminPassword')]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"computerName": "[parameters('vmName')]",
|
||||
"linuxConfiguration": {
|
||||
"ssh": {
|
||||
"publicKeys": [
|
||||
{
|
||||
"keyData": "",
|
||||
"path": "[variables('sshKeyPath')]"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"storageProfile": {
|
||||
"imageReference": {
|
||||
"id": "[resourceId(resourceGroup().name, 'Microsoft.Compute/images', 'ManagedImageName')]"
|
||||
},
|
||||
"osDisk": {
|
||||
"caching": "ReadWrite",
|
||||
"createOption": "FromImage",
|
||||
"name": "osdisk"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "Microsoft.Compute/virtualMachines"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('managedDiskApiVersion')]",
|
||||
"location": "",
|
||||
"name": "ManagedImageName",
|
||||
"properties": {
|
||||
"storageProfile": {
|
||||
"osDisk": {
|
||||
"blobUri": "",
|
||||
"osState": "",
|
||||
"osType": "Linux"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "Microsoft.Compute/images"
|
||||
}
|
||||
],
|
||||
"variables": {
|
||||
"addressPrefix": "10.0.0.0/16",
|
||||
"apiVersion": "2017-03-30",
|
||||
"location": "[resourceGroup().location]",
|
||||
"managedDiskApiVersion": "2017-03-30",
|
||||
"networkInterfacesApiVersion": "2017-04-01",
|
||||
"nicName": "packerNic",
|
||||
"publicIPAddressApiVersion": "2017-04-01",
|
||||
"publicIPAddressName": "packerPublicIP",
|
||||
"publicIPAddressType": "Dynamic",
|
||||
"sshKeyPath": "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]",
|
||||
"subnetAddressPrefix": "10.0.0.0/24",
|
||||
"subnetName": "packerSubnet",
|
||||
"subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",
|
||||
"virtualNetworkName": "packerNetwork",
|
||||
"virtualNetworkResourceGroup": "[resourceGroup().name]",
|
||||
"virtualNetworksApiVersion": "2017-04-01",
|
||||
"vmStorageAccountContainerName": "images",
|
||||
"vnetID": "[resourceId(variables('virtualNetworkResourceGroup'), 'Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
{
|
||||
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"adminPassword": {
|
||||
"type": "string"
|
||||
},
|
||||
"adminUsername": {
|
||||
"type": "string"
|
||||
},
|
||||
"dnsNameForPublicIP": {
|
||||
"type": "string"
|
||||
},
|
||||
"osDiskName": {
|
||||
"type": "string"
|
||||
},
|
||||
"storageAccountBlobEndpoint": {
|
||||
"type": "string"
|
||||
},
|
||||
"vmName": {
|
||||
"type": "string"
|
||||
},
|
||||
"vmSize": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "[variables('publicIPAddressApiVersion')]",
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('publicIPAddressName')]",
|
||||
"properties": {
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[parameters('dnsNameForPublicIP')]"
|
||||
},
|
||||
"publicIPAllocationMethod": "[variables('publicIPAddressType')]"
|
||||
},
|
||||
"type": "Microsoft.Network/publicIPAddresses"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('virtualNetworksApiVersion')]",
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('virtualNetworkName')]",
|
||||
"properties": {
|
||||
"addressSpace": {
|
||||
"addressPrefixes": [
|
||||
"[variables('addressPrefix')]"
|
||||
]
|
||||
},
|
||||
"subnets": [
|
||||
{
|
||||
"name": "[variables('subnetName')]",
|
||||
"properties": {
|
||||
"addressPrefix": "[variables('subnetAddressPrefix')]"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "Microsoft.Network/virtualNetworks"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('networkInterfacesApiVersion')]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
|
||||
"[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
|
||||
],
|
||||
"location": "[variables('location')]",
|
||||
"name": "[variables('nicName')]",
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"publicIPAddress": {
|
||||
"id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]"
|
||||
},
|
||||
"subnet": {
|
||||
"id": "[variables('subnetRef')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "Microsoft.Network/networkInterfaces"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]",
|
||||
"[concat('Microsoft.Compute/images/', 'packerManagedDisk')]"
|
||||
],
|
||||
"location": "[variables('location')]",
|
||||
"name": "[parameters('vmName')]",
|
||||
"properties": {
|
||||
"diagnosticsProfile": {
|
||||
"bootDiagnostics": {
|
||||
"enabled": false
|
||||
}
|
||||
},
|
||||
"hardwareProfile": {
|
||||
"vmSize": "[parameters('vmSize')]"
|
||||
},
|
||||
"networkProfile": {
|
||||
"networkInterfaces": [
|
||||
{
|
||||
"id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
|
||||
}
|
||||
]
|
||||
},
|
||||
"osProfile": {
|
||||
"adminPassword": "[parameters('adminPassword')]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"computerName": "[parameters('vmName')]",
|
||||
"linuxConfiguration": {
|
||||
"ssh": {
|
||||
"publicKeys": [
|
||||
{
|
||||
"keyData": "",
|
||||
"path": "[variables('sshKeyPath')]"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"storageProfile": {
|
||||
"imageReference": {
|
||||
"id": "[resourceId(resourceGroup().name, 'Microsoft.Compute/images', 'packerManagedDisk')]"
|
||||
},
|
||||
"osDisk": {
|
||||
"caching": "ReadWrite",
|
||||
"createOption": "FromImage",
|
||||
"name": "osdisk"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "Microsoft.Compute/virtualMachines"
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('managedDiskApiVersion')]",
|
||||
"location": "ignore",
|
||||
"name": "packerManagedDisk",
|
||||
"properties": {
|
||||
"storageProfile": {
|
||||
"imageReference": {
|
||||
"offer": "UbuntuServer",
|
||||
"publisher": "Canonical",
|
||||
"sku": "16.04-LTS",
|
||||
"version": "--version--"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "Microsoft.Compute/images"
|
||||
}
|
||||
],
|
||||
"variables": {
|
||||
"addressPrefix": "10.0.0.0/16",
|
||||
"apiVersion": "2017-03-30",
|
||||
"location": "[resourceGroup().location]",
|
||||
"managedDiskApiVersion": "2017-03-30",
|
||||
"networkInterfacesApiVersion": "2017-04-01",
|
||||
"nicName": "packerNic",
|
||||
"publicIPAddressApiVersion": "2017-04-01",
|
||||
"publicIPAddressName": "packerPublicIP",
|
||||
"publicIPAddressType": "Dynamic",
|
||||
"sshKeyPath": "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]",
|
||||
"subnetAddressPrefix": "10.0.0.0/24",
|
||||
"subnetName": "packerSubnet",
|
||||
"subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",
|
||||
"virtualNetworkName": "packerNetwork",
|
||||
"virtualNetworkResourceGroup": "[resourceGroup().name]",
|
||||
"virtualNetworksApiVersion": "2017-04-01",
|
||||
"vmStorageAccountContainerName": "images",
|
||||
"vnetID": "[resourceId(variables('virtualNetworkResourceGroup'), 'Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]"
|
||||
}
|
||||
}
|
|
@ -258,6 +258,74 @@ growpart:
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure the VM template is correct when building from a custom managed image.
|
||||
func TestVirtualMachineDeployment08(t *testing.T) {
|
||||
config := map[string]interface{}{
|
||||
"capture_name_prefix": "ignore",
|
||||
"capture_container_name": "ignore",
|
||||
"location": "ignore",
|
||||
"resource_group_name": "ignore",
|
||||
"storage_account": "ignore",
|
||||
"subscription_id": "ignore",
|
||||
"os_type": constants.Target_Linux,
|
||||
"communicator": "none",
|
||||
"managed_image_name": "ManagedImageName",
|
||||
"managed_image_resource_group_name": "ManagedImageResourceGroupName",
|
||||
"target_managed_image_name": "TargetManagedImageName",
|
||||
"target_managed_image_resource_group_name": "TargetManagedImageResourceGroupName",
|
||||
}
|
||||
|
||||
c, _, err := newConfig(config, getPackerConfiguration())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
deployment, err := GetVirtualMachineDeployment(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = approvaltests.VerifyJSONStruct(t, deployment.Properties.Template)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the VM template is correct when building from a platform managed image.
|
||||
func TestVirtualMachineDeployment09(t *testing.T) {
|
||||
config := map[string]interface{}{
|
||||
"capture_name_prefix": "ignore",
|
||||
"capture_container_name": "ignore",
|
||||
"location": "ignore",
|
||||
"resource_group_name": "ignore",
|
||||
"storage_account": "ignore",
|
||||
"subscription_id": "ignore",
|
||||
"os_type": constants.Target_Linux,
|
||||
"communicator": "none",
|
||||
"image_publisher": "Canonical",
|
||||
"image_offer": "UbuntuServer",
|
||||
"image_sku": "16.04-LTS",
|
||||
"image_version": "--version--",
|
||||
"target_managed_image_name": "TargetManagedImageName",
|
||||
"target_managed_image_resource_group_name": "TargetManagedImageResourceGroupName",
|
||||
}
|
||||
|
||||
c, _, err := newConfig(config, getPackerConfiguration())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
deployment, err := GetVirtualMachineDeployment(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = approvaltests.VerifyJSONStruct(t, deployment.Properties.Template)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the link values are not set, and the concrete values are set.
|
||||
func TestKeyVaultDeployment00(t *testing.T) {
|
||||
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
|
||||
|
|
|
@ -16,6 +16,7 @@ const (
|
|||
const (
|
||||
ArmCaptureTemplate string = "arm.CaptureTemplate"
|
||||
ArmComputeName string = "arm.ComputeName"
|
||||
ArmImageParameters string = "arm.ImageParameters"
|
||||
ArmCertificateUrl string = "arm.CertificateUrl"
|
||||
ArmDeploymentName string = "arm.DeploymentName"
|
||||
ArmNicName string = "arm.NicName"
|
||||
|
@ -28,4 +29,9 @@ const (
|
|||
ArmStorageAccountName string = "arm.StorageAccountName"
|
||||
ArmTags string = "arm.Tags"
|
||||
ArmVirtualMachineCaptureParameters string = "arm.VirtualMachineCaptureParameters"
|
||||
|
||||
ArmIsManagedImage string = "arm.IsManagedImage"
|
||||
ArmTargetManagedImageResourceGroupName string = "arm.TargetManagedImageResourceGroupName"
|
||||
ArmTargetManagedImageLocation string = "arm.TargetManagedImageLocation"
|
||||
ArmTargetManagedImageName string = "arm.TargetManagedImageName"
|
||||
)
|
||||
|
|
|
@ -9,11 +9,11 @@ import (
|
|||
|
||||
"github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
"github.com/hashicorp/packer/version"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -14,6 +14,7 @@ const (
|
|||
jsonIndent = " "
|
||||
|
||||
resourceKeyVaults = "Microsoft.KeyVault/vaults"
|
||||
resourceManagedDisk = "Microsoft.Compute/images"
|
||||
resourceNetworkInterfaces = "Microsoft.Network/networkInterfaces"
|
||||
resourcePublicIPAddresses = "Microsoft.Network/publicIPAddresses"
|
||||
resourceVirtualMachine = "Microsoft.Compute/virtualMachines"
|
||||
|
@ -24,6 +25,7 @@ const (
|
|||
|
||||
type TemplateBuilder struct {
|
||||
template *Template
|
||||
osType compute.OperatingSystemTypes
|
||||
}
|
||||
|
||||
func NewTemplateBuilder(template string) (*TemplateBuilder, error) {
|
||||
|
@ -57,6 +59,7 @@ func (s *TemplateBuilder) BuildLinux(sshAuthorizedKey string) error {
|
|||
},
|
||||
}
|
||||
|
||||
s.osType = compute.Linux
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -93,6 +96,80 @@ func (s *TemplateBuilder) BuildWindows(keyVaultName, winRMCertificateUrl string)
|
|||
},
|
||||
},
|
||||
}
|
||||
|
||||
s.osType = compute.Windows
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *TemplateBuilder) SetManagedDiskUrl(managedDiskImageName, location, blobUri string, osState compute.OperatingSystemStateTypes) error {
|
||||
resource, err := s.getResourceByType(resourceVirtualMachine)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resourceId := s.toResourceID(resourceManagedDisk, managedDiskImageName)
|
||||
profile := resource.Properties.StorageProfile
|
||||
profile.ImageReference = &compute.ImageReference{
|
||||
ID: to.StringPtr(resourceId),
|
||||
}
|
||||
profile.OsDisk.Vhd = nil
|
||||
|
||||
*resource.DependsOn = append(*resource.DependsOn, fmt.Sprintf("[concat('%s/', '%s')]", resourceManagedDisk, managedDiskImageName))
|
||||
|
||||
managedDiskResource := &Resource{
|
||||
Type: to.StringPtr(resourceManagedDisk),
|
||||
ApiVersion: to.StringPtr(s.toVariable("managedDiskApiVersion")),
|
||||
Name: to.StringPtr(managedDiskImageName),
|
||||
Location: to.StringPtr(location),
|
||||
Properties: &Properties{
|
||||
StorageProfile: &compute.StorageProfile{
|
||||
OsDisk: &compute.OSDisk{
|
||||
OsType: s.osType,
|
||||
OsState: to.StringPtr(fmt.Sprintf("%s", osState)),
|
||||
BlobUri: to.StringPtr(blobUri),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
*s.template.Resources = append(*s.template.Resources, *managedDiskResource)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *TemplateBuilder) SetManagedMarketplaceImage(location, publisher, offer, sku, version string) error {
|
||||
resource, err := s.getResourceByType(resourceVirtualMachine)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
managedDiskImageName := "packerManagedDisk"
|
||||
|
||||
resourceId := s.toResourceID(resourceManagedDisk, managedDiskImageName)
|
||||
profile := resource.Properties.StorageProfile
|
||||
profile.ImageReference = &compute.ImageReference{
|
||||
ID: to.StringPtr(resourceId),
|
||||
}
|
||||
profile.OsDisk.Vhd = nil
|
||||
*resource.DependsOn = append(*resource.DependsOn, fmt.Sprintf("[concat('%s/', '%s')]", resourceManagedDisk, managedDiskImageName))
|
||||
|
||||
managedDiskResource := &Resource{
|
||||
Type: to.StringPtr(resourceManagedDisk),
|
||||
Name: &managedDiskImageName,
|
||||
ApiVersion: to.StringPtr(s.toVariable("managedDiskApiVersion")),
|
||||
Location: to.StringPtr(location),
|
||||
Properties: &Properties{
|
||||
StorageProfile: &compute.StorageProfile{
|
||||
ImageReference: &compute.ImageReference{
|
||||
Publisher: &publisher,
|
||||
Offer: &offer,
|
||||
Sku: &sku,
|
||||
Version: &version,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
*s.template.Resources = append(*s.template.Resources, *managedDiskResource)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -347,7 +424,11 @@ const BasicTemplate = `{
|
|||
},
|
||||
"variables": {
|
||||
"addressPrefix": "10.0.0.0/16",
|
||||
"apiVersion": "2015-06-15",
|
||||
"apiVersion": "2017-03-30",
|
||||
"managedDiskApiVersion": "2017-03-30",
|
||||
"networkInterfacesApiVersion": "2017-04-01",
|
||||
"publicIPAddressApiVersion": "2017-04-01",
|
||||
"virtualNetworksApiVersion": "2017-04-01",
|
||||
"location": "[resourceGroup().location]",
|
||||
"nicName": "packerNic",
|
||||
"publicIPAddressName": "packerPublicIP",
|
||||
|
@ -363,7 +444,7 @@ const BasicTemplate = `{
|
|||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('publicIPAddressApiVersion')]",
|
||||
"type": "Microsoft.Network/publicIPAddresses",
|
||||
"name": "[variables('publicIPAddressName')]",
|
||||
"location": "[variables('location')]",
|
||||
|
@ -375,7 +456,7 @@ const BasicTemplate = `{
|
|||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('virtualNetworksApiVersion')]",
|
||||
"type": "Microsoft.Network/virtualNetworks",
|
||||
"name": "[variables('virtualNetworkName')]",
|
||||
"location": "[variables('location')]",
|
||||
|
@ -396,7 +477,7 @@ const BasicTemplate = `{
|
|||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "[variables('apiVersion')]",
|
||||
"apiVersion": "[variables('networkInterfacesApiVersion')]",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "[variables('nicName')]",
|
||||
"location": "[variables('location')]",
|
||||
|
|
|
@ -400,19 +400,19 @@ type APIErrorBase struct {
|
|||
// AvailabilitySet is create or update availability set parameters.
|
||||
type AvailabilitySet struct {
|
||||
autorest.Response `json:"-"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
*AvailabilitySetProperties `json:"properties,omitempty"`
|
||||
Sku *Sku `json:"sku,omitempty"`
|
||||
Sku *Sku `json:"sku,omitempty"`
|
||||
}
|
||||
|
||||
// AvailabilitySetListResult is the List Availability Set operation response.
|
||||
type AvailabilitySetListResult struct {
|
||||
autorest.Response `json:"-"`
|
||||
Value *[]AvailabilitySet `json:"value,omitempty"`
|
||||
Value *[]AvailabilitySet `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
// AvailabilitySetProperties is the instance view of a resource.
|
||||
|
@ -480,11 +480,11 @@ type HardwareProfile struct {
|
|||
// Image is describes an Image.
|
||||
type Image struct {
|
||||
autorest.Response `json:"-"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
*ImageProperties `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -501,8 +501,8 @@ type ImageDataDisk struct {
|
|||
// ImageListResult is the List Image operation response.
|
||||
type ImageListResult struct {
|
||||
autorest.Response `json:"-"`
|
||||
Value *[]Image `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
Value *[]Image `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
}
|
||||
|
||||
// ImageListResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||
|
@ -586,8 +586,8 @@ type LinuxConfiguration struct {
|
|||
// ListUsagesResult is the List Usages operation response.
|
||||
type ListUsagesResult struct {
|
||||
autorest.Response `json:"-"`
|
||||
Value *[]Usage `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
Value *[]Usage `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
}
|
||||
|
||||
// ListUsagesResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||
|
@ -605,13 +605,13 @@ func (client ListUsagesResult) ListUsagesResultPreparer() (*http.Request, error)
|
|||
// ListVirtualMachineExtensionImage is
|
||||
type ListVirtualMachineExtensionImage struct {
|
||||
autorest.Response `json:"-"`
|
||||
Value *[]VirtualMachineExtensionImage `json:"value,omitempty"`
|
||||
Value *[]VirtualMachineExtensionImage `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
// ListVirtualMachineImageResource is
|
||||
type ListVirtualMachineImageResource struct {
|
||||
autorest.Response `json:"-"`
|
||||
Value *[]VirtualMachineImageResource `json:"value,omitempty"`
|
||||
Value *[]VirtualMachineImageResource `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
// LongRunningOperationProperties is compute-specific operation properties,
|
||||
|
@ -628,7 +628,7 @@ type ManagedDiskParameters struct {
|
|||
|
||||
// NetworkInterfaceReference is describes a network interface reference.
|
||||
type NetworkInterfaceReference struct {
|
||||
ID *string `json:"id,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
*NetworkInterfaceReferenceProperties `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -646,16 +646,19 @@ type NetworkProfile struct {
|
|||
// OperationStatusResponse is operation status response
|
||||
type OperationStatusResponse struct {
|
||||
autorest.Response `json:"-"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Status *string `json:"status,omitempty"`
|
||||
StartTime *date.Time `json:"startTime,omitempty"`
|
||||
EndTime *date.Time `json:"endTime,omitempty"`
|
||||
Error *APIError `json:"error,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Status *string `json:"status,omitempty"`
|
||||
StartTime *date.Time `json:"startTime,omitempty"`
|
||||
EndTime *date.Time `json:"endTime,omitempty"`
|
||||
Error *APIError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// OSDisk is describes an Operating System disk.
|
||||
type OSDisk struct {
|
||||
OsType OperatingSystemTypes `json:"osType,omitempty"`
|
||||
OsState *string `json:"osState,omitempty"`
|
||||
StorageAccountType *string `json:"storageAccountType,omitempty"`
|
||||
BlobUri *string `json:"blobUri,omitempty"`
|
||||
EncryptionSettings *DiskEncryptionSettings `json:"encryptionSettings,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Vhd *VirtualHardDisk `json:"vhd,omitempty"`
|
||||
|
@ -784,15 +787,15 @@ type VirtualHardDisk struct {
|
|||
// VirtualMachine is describes a Virtual Machine.
|
||||
type VirtualMachine struct {
|
||||
autorest.Response `json:"-"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
Plan *Plan `json:"plan,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
Plan *Plan `json:"plan,omitempty"`
|
||||
*VirtualMachineProperties `json:"properties,omitempty"`
|
||||
Resources *[]VirtualMachineExtension `json:"resources,omitempty"`
|
||||
Identity *VirtualMachineIdentity `json:"identity,omitempty"`
|
||||
Resources *[]VirtualMachineExtension `json:"resources,omitempty"`
|
||||
Identity *VirtualMachineIdentity `json:"identity,omitempty"`
|
||||
}
|
||||
|
||||
// VirtualMachineAgentInstanceView is the instance view of the VM Agent running
|
||||
|
@ -813,7 +816,7 @@ type VirtualMachineCaptureParameters struct {
|
|||
// VirtualMachineCaptureResult is resource Id.
|
||||
type VirtualMachineCaptureResult struct {
|
||||
autorest.Response `json:"-"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
*VirtualMachineCaptureResultProperties `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -826,11 +829,11 @@ type VirtualMachineCaptureResultProperties struct {
|
|||
// VirtualMachineExtension is describes a Virtual Machine Extension.
|
||||
type VirtualMachineExtension struct {
|
||||
autorest.Response `json:"-"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
*VirtualMachineExtensionProperties `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -845,11 +848,11 @@ type VirtualMachineExtensionHandlerInstanceView struct {
|
|||
// VirtualMachineExtensionImage is describes a Virtual Machine Extension Image.
|
||||
type VirtualMachineExtensionImage struct {
|
||||
autorest.Response `json:"-"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
*VirtualMachineExtensionImageProperties `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -897,10 +900,10 @@ type VirtualMachineIdentity struct {
|
|||
// VirtualMachineImage is describes a Virtual Machine Image.
|
||||
type VirtualMachineImage struct {
|
||||
autorest.Response `json:"-"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
*VirtualMachineImageProperties `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -935,8 +938,8 @@ type VirtualMachineInstanceView struct {
|
|||
// VirtualMachineListResult is the List Virtual Machine operation response.
|
||||
type VirtualMachineListResult struct {
|
||||
autorest.Response `json:"-"`
|
||||
Value *[]VirtualMachine `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
Value *[]VirtualMachine `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
}
|
||||
|
||||
// VirtualMachineListResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||
|
@ -968,15 +971,15 @@ type VirtualMachineProperties struct {
|
|||
// VirtualMachineScaleSet is describes a Virtual Machine Scale Set.
|
||||
type VirtualMachineScaleSet struct {
|
||||
autorest.Response `json:"-"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
Sku *Sku `json:"sku,omitempty"`
|
||||
Plan *Plan `json:"plan,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
Sku *Sku `json:"sku,omitempty"`
|
||||
Plan *Plan `json:"plan,omitempty"`
|
||||
*VirtualMachineScaleSetProperties `json:"properties,omitempty"`
|
||||
Identity *VirtualMachineScaleSetIdentity `json:"identity,omitempty"`
|
||||
Identity *VirtualMachineScaleSetIdentity `json:"identity,omitempty"`
|
||||
}
|
||||
|
||||
// VirtualMachineScaleSetDataDisk is describes a virtual machine scale set data
|
||||
|
@ -993,8 +996,8 @@ type VirtualMachineScaleSetDataDisk struct {
|
|||
// VirtualMachineScaleSetExtension is describes a Virtual Machine Scale Set
|
||||
// Extension.
|
||||
type VirtualMachineScaleSetExtension struct {
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
*VirtualMachineScaleSetExtensionProperties `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -1028,9 +1031,9 @@ type VirtualMachineScaleSetIdentity struct {
|
|||
// scale set.
|
||||
type VirtualMachineScaleSetInstanceView struct {
|
||||
autorest.Response `json:"-"`
|
||||
VirtualMachine *VirtualMachineScaleSetInstanceViewStatusesSummary `json:"virtualMachine,omitempty"`
|
||||
Extensions *[]VirtualMachineScaleSetVMExtensionsSummary `json:"extensions,omitempty"`
|
||||
Statuses *[]InstanceViewStatus `json:"statuses,omitempty"`
|
||||
VirtualMachine *VirtualMachineScaleSetInstanceViewStatusesSummary `json:"virtualMachine,omitempty"`
|
||||
Extensions *[]VirtualMachineScaleSetVMExtensionsSummary `json:"extensions,omitempty"`
|
||||
Statuses *[]InstanceViewStatus `json:"statuses,omitempty"`
|
||||
}
|
||||
|
||||
// VirtualMachineScaleSetInstanceViewStatusesSummary is instance view statuses
|
||||
|
@ -1042,8 +1045,8 @@ type VirtualMachineScaleSetInstanceViewStatusesSummary struct {
|
|||
// VirtualMachineScaleSetIPConfiguration is describes a virtual machine scale
|
||||
// set network profile's IP configuration.
|
||||
type VirtualMachineScaleSetIPConfiguration struct {
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
*VirtualMachineScaleSetIPConfigurationProperties `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -1060,8 +1063,8 @@ type VirtualMachineScaleSetIPConfigurationProperties struct {
|
|||
// response.
|
||||
type VirtualMachineScaleSetListResult struct {
|
||||
autorest.Response `json:"-"`
|
||||
Value *[]VirtualMachineScaleSet `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
Value *[]VirtualMachineScaleSet `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
}
|
||||
|
||||
// VirtualMachineScaleSetListResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||
|
@ -1080,8 +1083,8 @@ func (client VirtualMachineScaleSetListResult) VirtualMachineScaleSetListResultP
|
|||
// Skus operation response.
|
||||
type VirtualMachineScaleSetListSkusResult struct {
|
||||
autorest.Response `json:"-"`
|
||||
Value *[]VirtualMachineScaleSetSku `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
Value *[]VirtualMachineScaleSetSku `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
}
|
||||
|
||||
// VirtualMachineScaleSetListSkusResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||
|
@ -1100,8 +1103,8 @@ func (client VirtualMachineScaleSetListSkusResult) VirtualMachineScaleSetListSku
|
|||
// operation response.
|
||||
type VirtualMachineScaleSetListWithLinkResult struct {
|
||||
autorest.Response `json:"-"`
|
||||
Value *[]VirtualMachineScaleSet `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
Value *[]VirtualMachineScaleSet `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
}
|
||||
|
||||
// VirtualMachineScaleSetListWithLinkResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||
|
@ -1125,8 +1128,8 @@ type VirtualMachineScaleSetManagedDiskParameters struct {
|
|||
// VirtualMachineScaleSetNetworkConfiguration is describes a virtual machine
|
||||
// scale set network profile's network configurations.
|
||||
type VirtualMachineScaleSetNetworkConfiguration struct {
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
*VirtualMachineScaleSetNetworkConfigurationProperties `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -1205,16 +1208,16 @@ type VirtualMachineScaleSetStorageProfile struct {
|
|||
// machine.
|
||||
type VirtualMachineScaleSetVM struct {
|
||||
autorest.Response `json:"-"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
InstanceID *string `json:"instanceId,omitempty"`
|
||||
Sku *Sku `json:"sku,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Tags *map[string]*string `json:"tags,omitempty"`
|
||||
InstanceID *string `json:"instanceId,omitempty"`
|
||||
Sku *Sku `json:"sku,omitempty"`
|
||||
*VirtualMachineScaleSetVMProperties `json:"properties,omitempty"`
|
||||
Plan *Plan `json:"plan,omitempty"`
|
||||
Resources *[]VirtualMachineExtension `json:"resources,omitempty"`
|
||||
Plan *Plan `json:"plan,omitempty"`
|
||||
Resources *[]VirtualMachineExtension `json:"resources,omitempty"`
|
||||
}
|
||||
|
||||
// VirtualMachineScaleSetVMExtensionsSummary is extensions summary for virtual
|
||||
|
@ -1255,8 +1258,8 @@ type VirtualMachineScaleSetVMInstanceView struct {
|
|||
// operation response.
|
||||
type VirtualMachineScaleSetVMListResult struct {
|
||||
autorest.Response `json:"-"`
|
||||
Value *[]VirtualMachineScaleSetVM `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
Value *[]VirtualMachineScaleSetVM `json:"value,omitempty"`
|
||||
NextLink *string `json:"nextLink,omitempty"`
|
||||
}
|
||||
|
||||
// VirtualMachineScaleSetVMListResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||
|
@ -1309,7 +1312,7 @@ type VirtualMachineSize struct {
|
|||
// VirtualMachineSizeListResult is the List Virtual Machine operation response.
|
||||
type VirtualMachineSizeListResult struct {
|
||||
autorest.Response `json:"-"`
|
||||
Value *[]VirtualMachineSize `json:"value,omitempty"`
|
||||
Value *[]VirtualMachineSize `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
// VirtualMachineStatusCodeCount is the status code and count of the virtual
|
||||
|
|
Loading…
Reference in New Issue