diff --git a/builder/azure/arm/artifact.go b/builder/azure/arm/artifact.go
index 5de9f90e1..eade5017b 100644
--- a/builder/azure/arm/artifact.go
+++ b/builder/azure/arm/artifact.go
@@ -16,11 +16,25 @@ const (
)
type Artifact struct {
+ // VHD
StorageAccountLocation string
OSDiskUri string
TemplateUri string
OSDiskUriReadOnlySas string
TemplateUriReadOnlySas string
+
+ // Managed Image
+ ManagedImageResourceGroupName string
+ ManagedImageName string
+ ManagedImageLocation string
+}
+
+func NewManagedImageArtifact(resourceGroup, name, location string) (*Artifact, error) {
+ return &Artifact{
+ ManagedImageResourceGroupName: resourceGroup,
+ ManagedImageName: name,
+ ManagedImageLocation: location,
+ }, nil
}
func NewArtifact(template *CaptureTemplate, getSasUrl func(name string) string) (*Artifact, error) {
@@ -78,6 +92,10 @@ func storageUriToTemplateUri(su *url.URL) (*url.URL, error) {
return url.Parse(strings.Replace(su.String(), filename, templateFilename, 1))
}
+func (a *Artifact) isMangedImage() bool {
+ return a.ManagedImageResourceGroupName != ""
+}
+
func (*Artifact) BuilderId() string {
return BuilderId
}
@@ -103,11 +121,17 @@ func (a *Artifact) String() string {
var buf bytes.Buffer
buf.WriteString(fmt.Sprintf("%s:\n\n", a.BuilderId()))
- buf.WriteString(fmt.Sprintf("StorageAccountLocation: %s\n", a.StorageAccountLocation))
- buf.WriteString(fmt.Sprintf("OSDiskUri: %s\n", a.OSDiskUri))
- buf.WriteString(fmt.Sprintf("OSDiskUriReadOnlySas: %s\n", a.OSDiskUriReadOnlySas))
- buf.WriteString(fmt.Sprintf("TemplateUri: %s\n", a.TemplateUri))
- buf.WriteString(fmt.Sprintf("TemplateUriReadOnlySas: %s\n", a.TemplateUriReadOnlySas))
+ if a.isMangedImage() {
+ buf.WriteString(fmt.Sprintf("ManagedImageResourceGroupName: %s\n", a.ManagedImageResourceGroupName))
+ buf.WriteString(fmt.Sprintf("ManagedImageName: %s\n", a.ManagedImageName))
+ buf.WriteString(fmt.Sprintf("ManagedImageLocation: %s\n", a.ManagedImageLocation))
+ } else {
+ buf.WriteString(fmt.Sprintf("StorageAccountLocation: %s\n", a.StorageAccountLocation))
+ buf.WriteString(fmt.Sprintf("OSDiskUri: %s\n", a.OSDiskUri))
+ buf.WriteString(fmt.Sprintf("OSDiskUriReadOnlySas: %s\n", a.OSDiskUriReadOnlySas))
+ buf.WriteString(fmt.Sprintf("TemplateUri: %s\n", a.TemplateUri))
+ buf.WriteString(fmt.Sprintf("TemplateUriReadOnlySas: %s\n", a.TemplateUriReadOnlySas))
+ }
return buf.String()
}
diff --git a/builder/azure/arm/azure_client.go b/builder/azure/arm/azure_client.go
index 10e3d42c0..88a6990af 100644
--- a/builder/azure/arm/azure_client.go
+++ b/builder/azure/arm/azure_client.go
@@ -180,23 +180,27 @@ func NewAzureClient(subscriptionID, resourceGroupName, storageAccountName string
azureClient.VaultClient.ResponseInspector = byInspecting(maxlen)
azureClient.VaultClient.UserAgent += packerUserAgent
- accountKeys, err := azureClient.AccountsClient.ListKeys(resourceGroupName, storageAccountName)
- if err != nil {
- return nil, err
+ // If this is a managed disk build, this should be ignored.
+ if resourceGroupName != "" && storageAccountName != "" {
+ accountKeys, err := azureClient.AccountsClient.ListKeys(resourceGroupName, storageAccountName)
+ if err != nil {
+ return nil, err
+ }
+
+ storageClient, err := storage.NewClient(
+ storageAccountName,
+ *(*accountKeys.Keys)[0].Value,
+ cloud.StorageEndpointSuffix,
+ storage.DefaultAPIVersion,
+ true /*useHttps*/)
+
+ if err != nil {
+ return nil, err
+ }
+
+ azureClient.BlobStorageClient = storageClient.GetBlobService()
}
- storageClient, err := storage.NewClient(
- storageAccountName,
- *(*accountKeys.Keys)[0].Value,
- cloud.StorageEndpointSuffix,
- storage.DefaultAPIVersion,
- true /*useHttps*/)
-
- if err != nil {
- return nil, err
- }
-
- azureClient.BlobStorageClient = storageClient.GetBlobService()
return azureClient, nil
}
diff --git a/builder/azure/arm/builder.go b/builder/azure/arm/builder.go
index ef92f4cbc..a9a435a22 100644
--- a/builder/azure/arm/builder.go
+++ b/builder/azure/arm/builder.go
@@ -104,14 +104,16 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
}
}
- 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.StorageAccount != "" {
+ 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)
+ if !equalLocation(*account.Location, b.config.Location) {
+ 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
@@ -197,7 +199,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
return nil, errors.New("Build was halted.")
}
- if template, ok := b.stateBag.GetOk(constants.ArmCaptureTemplate); ok {
+ if b.config.isManagedImage() {
+ return NewManagedImageArtifact(b.config.ManagedImageResourceGroupName, b.config.ManagedImageName, b.config.manageImageLocation)
+ } else if template, ok := b.stateBag.GetOk(constants.ArmCaptureTemplate); ok {
return NewArtifact(
template.(*CaptureTemplate),
func(name string) string {
diff --git a/builder/azure/arm/config.go b/builder/azure/arm/config.go
index 0f42f6511..ee3d124f1 100644
--- a/builder/azure/arm/config.go
+++ b/builder/azure/arm/config.go
@@ -470,39 +470,61 @@ func assertRequiredParametersSet(c *Config, errs *packer.MultiError) {
/////////////////////////////////////////////
// Capture
- if c.CaptureContainerName == "" {
- errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_container_name must be specified"))
+ if c.CaptureContainerName == "" && c.ManagedImageName == "" {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_container_name or managed_image_name must be specified"))
}
- if !reCaptureContainerName.MatchString(c.CaptureContainerName) {
- errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_container_name must satisfy the regular expression %q.", reCaptureContainerName.String()))
+ if c.CaptureNamePrefix == "" && c.ManagedImageResourceGroupName == "" {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_name_prefix or managed_image_resource_group_name must be specified"))
}
- if strings.HasSuffix(c.CaptureContainerName, "-") {
- errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_container_name must not end with a hyphen, e.g. '-'."))
+ if (c.CaptureNamePrefix != "" || c.CaptureContainerName != "") && (c.ManagedImageResourceGroupName != "" || c.ManagedImageName != "") {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("Either a VHD or a managed image can be built, but not both. Please specify either capture_container_name and capture_name_prefix or managed_image_resource_group_name and managed_image_name."))
}
- if strings.Contains(c.CaptureContainerName, "--") {
- errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_container_name must not contain consecutive hyphens, e.g. '--'."))
- }
+ if c.CaptureContainerName != "" {
+ if !reCaptureContainerName.MatchString(c.CaptureContainerName) {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_container_name must satisfy the regular expression %q.", reCaptureContainerName.String()))
+ }
- if c.CaptureNamePrefix == "" {
- errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_name_prefix must be specified"))
- }
+ if strings.HasSuffix(c.CaptureContainerName, "-") {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_container_name must not end with a hyphen, e.g. '-'."))
+ }
- if !reCaptureNamePrefix.MatchString(c.CaptureNamePrefix) {
- errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_name_prefix must satisfy the regular expression %q.", reCaptureNamePrefix.String()))
- }
+ if strings.Contains(c.CaptureContainerName, "--") {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_container_name must not contain consecutive hyphens, e.g. '--'."))
+ }
- if strings.HasSuffix(c.CaptureNamePrefix, "-") || strings.HasSuffix(c.CaptureNamePrefix, ".") {
- errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_name_prefix must not end with a hyphen or period."))
+ if c.CaptureNamePrefix == "" {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_name_prefix must be specified"))
+ }
+
+ if !reCaptureNamePrefix.MatchString(c.CaptureNamePrefix) {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_name_prefix must satisfy the regular expression %q.", reCaptureNamePrefix.String()))
+ }
+
+ if strings.HasSuffix(c.CaptureNamePrefix, "-") || strings.HasSuffix(c.CaptureNamePrefix, ".") {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("A capture_name_prefix must not end with a hyphen or period."))
+ }
}
/////////////////////////////////////////////
// Compute
- if c.ImageUrl != "" &&
- (c.CustomManagedImageName != "" || c.CustomManagedImageResourceGroupName != "") &&
- (c.ImagePublisher != "" || c.ImageOffer != "" || c.ImageSku != "") {
+ toInt := func(b bool) int {
+ if b {
+ return 1
+ } else {
+ return 0
+ }
+ }
+
+ isImageUrl := c.ImageUrl != ""
+ isCustomManagedImage := c.CustomManagedImageName != "" || c.CustomManagedImageResourceGroupName != ""
+ isPlatformImage := c.ImagePublisher != "" || c.ImageOffer != "" || c.ImageSku != ""
+
+ countSourceInputs := toInt(isImageUrl) + toInt(isCustomManagedImage) + toInt(isPlatformImage)
+
+ if countSourceInputs > 1 {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("Specify either a VHD (image_url), Image Reference (image_publisher, image_offer, image_sku) or a Managed Disk (custom_managed_disk_image_name, custom_managed_disk_resource_group_name"))
}
@@ -541,12 +563,23 @@ func assertRequiredParametersSet(c *Config, errs *packer.MultiError) {
/////////////////////////////////////////////
// Deployment
- if c.StorageAccount == "" {
- errs = packer.MultiErrorAppend(errs, fmt.Errorf("A storage_account must be specified"))
+ xor := func(a, b bool) bool {
+ return (a || b) && !(a && b)
}
- if c.ResourceGroupName == "" {
- errs = packer.MultiErrorAppend(errs, fmt.Errorf("A resource_group_name must be specified"))
+
+ if !xor((c.StorageAccount != "" || c.ResourceGroupName != ""), (c.ManagedImageName != "" || c.ManagedImageResourceGroupName != "")) {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("Specify either a VHD (storage_account and resource_group_name) or Managed Image (managed_image_resource_group_name and managed_image_name) output"))
}
+
+ if c.ManagedImageName == "" && c.ManagedImageResourceGroupName == "" {
+ if c.StorageAccount == "" {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("A storage_account must be specified"))
+ }
+ if c.ResourceGroupName == "" {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("A resource_group_name must be specified"))
+ }
+ }
+
if c.VirtualNetworkName == "" && c.VirtualNetworkResourceGroupName != "" {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("If virtual_network_resource_group_name is specified, so must virtual_network_name"))
}
diff --git a/builder/azure/arm/config_test.go b/builder/azure/arm/config_test.go
index 1d859d014..835454718 100644
--- a/builder/azure/arm/config_test.go
+++ b/builder/azure/arm/config_test.go
@@ -737,6 +737,95 @@ func TestConfigShouldRejectMissingCustomDataFile(t *testing.T) {
}
}
+func TestConfigShouldAcceptPlatformManagedImageBuild(t *testing.T) {
+ config := map[string]interface{}{
+ "image_offer": "ignore",
+ "image_publisher": "ignore",
+ "image_sku": "ignore",
+ "location": "ignore",
+ "subscription_id": "ignore",
+ "communicator": "none",
+ "managed_image_resource_group_name": "ignore",
+ "managed_image_name": "ignore",
+
+ // Does not matter for this test case, just pick one.
+ "os_type": constants.Target_Linux,
+ }
+
+ _, _, err := newConfig(config, getPackerConfiguration())
+ if err != nil {
+ t.Fatal("expected config to accept platform managed image build")
+ }
+}
+
+// If the user specified a build for a VHD and a Managed Image it should be rejected.
+func TestConfigShouldRejectVhdAndManagedImageOutput(t *testing.T) {
+ config := map[string]interface{}{
+ "image_offer": "ignore",
+ "image_publisher": "ignore",
+ "image_sku": "ignore",
+ "location": "ignore",
+ "subscription_id": "ignore",
+ "communicator": "none",
+ "capture_container_name": "ignore",
+ "capture_name_prefix": "ignore",
+ "managed_image_resource_group_name": "ignore",
+ "managed_image_name": "ignore",
+
+ // Does not matter for this test case, just pick one.
+ "os_type": constants.Target_Linux,
+ }
+
+ _, _, err := newConfig(config, getPackerConfiguration())
+ if err == nil {
+ t.Fatal("expected config to reject VHD and Managed Image build")
+ }
+}
+
+func TestConfigShouldRejectCustomAndPlatformManagedImageBuild(t *testing.T) {
+ config := map[string]interface{}{
+ "custom_managed_image_resource_group_name": "ignore",
+ "custom_managed_image_name": "ignore",
+ "image_offer": "ignore",
+ "image_publisher": "ignore",
+ "image_sku": "ignore",
+ "location": "ignore",
+ "subscription_id": "ignore",
+ "communicator": "none",
+ "managed_image_resource_group_name": "ignore",
+ "managed_image_name": "ignore",
+
+ // Does not matter for this test case, just pick one.
+ "os_type": constants.Target_Linux,
+ }
+
+ _, _, err := newConfig(config, getPackerConfiguration())
+ if err == nil {
+ t.Fatal("expected config to reject custom and platform input for a managed image build")
+ }
+}
+
+func TestConfigShouldRejectCustomAndImageUrlForManagedImageBuild(t *testing.T) {
+ config := map[string]interface{}{
+ "image_url": "ignore",
+ "custom_managed_image_resource_group_name": "ignore",
+ "custom_managed_image_name": "ignore",
+ "location": "ignore",
+ "subscription_id": "ignore",
+ "communicator": "none",
+ "managed_image_resource_group_name": "ignore",
+ "managed_image_name": "ignore",
+
+ // Does not matter for this test case, just pick one.
+ "os_type": constants.Target_Linux,
+ }
+
+ _, _, err := newConfig(config, getPackerConfiguration())
+ if err == nil {
+ t.Fatal("expected config to reject custom and platform input for a managed image build")
+ }
+}
+
func getArmBuilderConfiguration() map[string]string {
m := make(map[string]string)
for _, v := range requiredConfigValues {
diff --git a/builder/azure/arm/template_factory_test.go b/builder/azure/arm/template_factory_test.go
index 0301b1012..8a6e0c650 100644
--- a/builder/azure/arm/template_factory_test.go
+++ b/builder/azure/arm/template_factory_test.go
@@ -261,11 +261,7 @@ 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",
@@ -294,11 +290,7 @@ func TestVirtualMachineDeployment08(t *testing.T) {
// 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",
diff --git a/examples/azure/centos.json b/examples/azure/centos.json
index 26538467f..1b0e7a633 100644
--- a/examples/azure/centos.json
+++ b/examples/azure/centos.json
@@ -28,12 +28,12 @@
"os_type": "Linux",
"image_publisher": "OpenLogic",
"image_offer": "CentOS",
- "image_sku": "7.2",
+ "image_sku": "7.3",
"image_version": "latest",
"ssh_pty": "true",
"location": "South Central US",
- "vm_size": "Standard_A2"
+ "vm_size": "Standard_DS2_v2"
}],
"provisioners": [{
"execute_command": "echo '{{user `ssh_pass`}}' | {{ .Vars }} sudo -S -E sh '{{ .Path }}'",
diff --git a/examples/azure/debian.json b/examples/azure/debian.json
index 3e313a48f..112ca4993 100644
--- a/examples/azure/debian.json
+++ b/examples/azure/debian.json
@@ -30,7 +30,7 @@
"ssh_pty": "true",
"location": "South Central US",
- "vm_size": "Standard_A2"
+ "vm_size": "Standard_DS2_v2"
}],
"provisioners": [{
"execute_command": "echo '{{user `ssh_pass`}}' | {{ .Vars }} sudo -S -E sh '{{ .Path }}'",
diff --git a/examples/azure/linux_custom_image.json b/examples/azure/linux_custom_image.json
index 4f4be6ca4..efbd3bef0 100644
--- a/examples/azure/linux_custom_image.json
+++ b/examples/azure/linux_custom_image.json
@@ -28,7 +28,7 @@
},
"location": "West US",
- "vm_size": "Standard_A2"
+ "vm_size": "Standard_DS2_v2"
}
],
"provisioners": [{
diff --git a/examples/azure/linux_custom_managed_image.json b/examples/azure/linux_custom_managed_image.json
index 62269b0ee..79dcc4d26 100644
--- a/examples/azure/linux_custom_managed_image.json
+++ b/examples/azure/linux_custom_managed_image.json
@@ -2,8 +2,6 @@
"variables": {
"client_id": "{{env `ARM_CLIENT_ID`}}",
"client_secret": "{{env `ARM_CLIENT_SECRET`}}",
- "resource_group": "{{env `ARM_RESOURCE_GROUP`}}",
- "storage_account": "{{env `ARM_STORAGE_ACCOUNT`}}",
"subscription_id": "{{env `ARM_SUBSCRIPTION_ID`}}"
},
"builders": [
@@ -12,13 +10,8 @@
"client_id": "{{user `client_id`}}",
"client_secret": "{{user `client_secret`}}",
- "resource_group_name": "{{user `resource_group`}}",
- "storage_account": "{{user `storage_account`}}",
"subscription_id": "{{user `subscription_id`}}",
- "capture_container_name": "images",
- "capture_name_prefix": "packer",
-
"os_type": "Linux",
"custom_managed_image_resource_group_name": "MyResourceGroup",
"custom_managed_image_name": "MyImage",
@@ -31,7 +24,7 @@
},
"location": "West US",
- "vm_size": "Standard_A2"
+ "vm_size": "Standard_DS2_v2"
}
],
"provisioners": [{
diff --git a/examples/azure/rhel.json b/examples/azure/rhel.json
new file mode 100644
index 000000000..7c4160268
--- /dev/null
+++ b/examples/azure/rhel.json
@@ -0,0 +1,48 @@
+{
+ "variables": {
+ "client_id": "{{env `ARM_CLIENT_ID`}}",
+ "client_secret": "{{env `ARM_CLIENT_SECRET`}}",
+ "resource_group": "{{env `ARM_RESOURCE_GROUP`}}",
+ "storage_account": "{{env `ARM_STORAGE_ACCOUNT`}}",
+ "subscription_id": "{{env `ARM_SUBSCRIPTION_ID`}}",
+ "tenant_id": "{{env `ARM_TENANT_ID`}}",
+ "ssh_user": "centos",
+ "ssh_pass": null
+ },
+ "builders": [{
+ "type": "azure-arm",
+
+ "client_id": "{{user `client_id`}}",
+ "client_secret": "{{user `client_secret`}}",
+ "resource_group_name": "{{user `resource_group`}}",
+ "storage_account": "{{user `storage_account`}}",
+ "subscription_id": "{{user `subscription_id`}}",
+ "tenant_id": "{{user `tenant_id`}}",
+
+ "capture_container_name": "images",
+ "capture_name_prefix": "packer",
+
+ "ssh_username": "{{user `ssh_user`}}",
+ "ssh_password": "{{user `ssh_pass`}}",
+
+ "os_type": "Linux",
+ "image_publisher": "RedHat",
+ "image_offer": "RHEL",
+ "image_sku": "7.3",
+ "image_version": "latest",
+ "ssh_pty": "true",
+
+ "location": "South Central US",
+ "vm_size": "Standard_DS2_v2"
+ }],
+ "provisioners": [{
+ "execute_command": "echo '{{user `ssh_pass`}}' | {{ .Vars }} sudo -S -E sh '{{ .Path }}'",
+ "inline": [
+ "yum update -y",
+ "/usr/sbin/waagent -force -deprovision+user && export HISTSIZE=0 && sync"
+ ],
+ "inline_shebang": "/bin/sh -x",
+ "type": "shell",
+ "skip_clean": true
+ }]
+}
diff --git a/examples/azure/opensuse.json b/examples/azure/suse.json
similarity index 93%
rename from examples/azure/opensuse.json
rename to examples/azure/suse.json
index 2bb462191..c99b364ec 100644
--- a/examples/azure/opensuse.json
+++ b/examples/azure/suse.json
@@ -25,12 +25,12 @@
"os_type": "Linux",
"image_publisher": "SUSE",
- "image_offer": "openSUSE",
- "image_sku": "13.2",
+ "image_offer": "SLES",
+ "image_sku": "12-SP2",
"ssh_pty": "true",
"location": "South Central US",
- "vm_size": "Standard_A2"
+ "vm_size": "Standard_DS2_v2"
}],
"provisioners": [{
"execute_command": "echo '{{user `ssh_pass`}}' | {{ .Vars }} sudo -S -E sh '{{ .Path }}'",
diff --git a/examples/azure/ubuntu.json b/examples/azure/ubuntu.json
index e90ab8ede..a9c657d06 100644
--- a/examples/azure/ubuntu.json
+++ b/examples/azure/ubuntu.json
@@ -21,7 +21,7 @@
"os_type": "Linux",
"image_publisher": "Canonical",
"image_offer": "UbuntuServer",
- "image_sku": "16.04.0-LTS",
+ "image_sku": "16.04-LTS",
"azure_tags": {
"dept": "engineering",
@@ -29,7 +29,7 @@
},
"location": "West US",
- "vm_size": "Standard_A2"
+ "vm_size": "Standard_DS2_v2"
}],
"provisioners": [{
"execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'",
diff --git a/examples/azure/ubuntu_managed_image.json b/examples/azure/ubuntu_managed_image.json
index b8e480ba4..ddb4a49c9 100644
--- a/examples/azure/ubuntu_managed_image.json
+++ b/examples/azure/ubuntu_managed_image.json
@@ -2,8 +2,6 @@
"variables": {
"client_id": "{{env `ARM_CLIENT_ID`}}",
"client_secret": "{{env `ARM_CLIENT_SECRET`}}",
- "resource_group": "{{env `ARM_RESOURCE_GROUP`}}",
- "storage_account": "{{env `ARM_STORAGE_ACCOUNT`}}",
"subscription_id": "{{env `ARM_SUBSCRIPTION_ID`}}"
},
"builders": [{
@@ -11,13 +9,8 @@
"client_id": "{{user `client_id`}}",
"client_secret": "{{user `client_secret`}}",
- "resource_group_name": "{{user `resource_group`}}",
- "storage_account": "{{user `storage_account`}}",
"subscription_id": "{{user `subscription_id`}}",
- "capture_container_name": "images",
- "capture_name_prefix": "packer",
-
"os_type": "Linux",
"image_publisher": "Canonical",
"image_offer": "UbuntuServer",
@@ -32,7 +25,7 @@
},
"location": "West US",
- "vm_size": "Standard_A2"
+ "vm_size": "Standard_DS2_v2"
}],
"provisioners": [{
"execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'",
diff --git a/examples/azure/ubuntu_quickstart.json b/examples/azure/ubuntu_quickstart.json
index 22bc210c6..15166d131 100644
--- a/examples/azure/ubuntu_quickstart.json
+++ b/examples/azure/ubuntu_quickstart.json
@@ -20,7 +20,7 @@
"image_sku": "16.04-LTS",
"location": "West US",
- "vm_size": "Standard_DS1_v2"
+ "vm_size": "Standard_DS2_v2"
}],
"provisioners": [{
"execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'",
diff --git a/examples/azure/windows.json b/examples/azure/windows.json
index b96f06559..8493f82cb 100644
--- a/examples/azure/windows.json
+++ b/examples/azure/windows.json
@@ -32,7 +32,7 @@
"winrm_username": "packer",
"location": "West US",
- "vm_size": "Standard_A2"
+ "vm_size": "Standard_DS2_v2"
}],
"provisioners": [{
"type": "powershell",
diff --git a/examples/azure/windows_custom_image.json b/examples/azure/windows_custom_image.json
index f8d95136d..b411555a7 100644
--- a/examples/azure/windows_custom_image.json
+++ b/examples/azure/windows_custom_image.json
@@ -28,7 +28,7 @@
},
"location": "West US",
- "vm_size": "Standard_A2"
+ "vm_size": "Standard_DS2_v2"
}
],
"provisioners": [{
diff --git a/website/source/docs/builders/azure.html.md b/website/source/docs/builders/azure.html.md
index adb0a4a2b..750a2fe66 100644
--- a/website/source/docs/builders/azure.html.md
+++ b/website/source/docs/builders/azure.html.md
@@ -29,15 +29,8 @@ builder.
- `client_secret` (string) The password or secret for your service principal.
-- `resource_group_name` (string) Resource group under which the final artifact will be stored.
-
-- `storage_account` (string) Storage account under which the final artifact will be stored.
-
- `subscription_id` (string) Subscription under which the build will be performed. **The service principal specified in `client_id` must have full access to this subscription.**
-
-- `capture_container_name` (string) Destination container name. Essentially the "directory" where your VHD will be organized in Azure. The captured VHD's URL will be .blob.core.windows.net/system/Microsoft.Compute/Images//.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.vhd.
-
-- `capture_name_prefix` (string) VHD prefix. The final artifacts will be named `PREFIX-osDisk.UUID` and `PREFIX-vmTemplate.UUID`.
+- `capture_container_name` (string) Destination container name. Essentially the "directory" where your VHD will be organized in Azure. The captured VHD's URL will be https://.blob.core.windows.net/system/Microsoft.Compute/Images//.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.vhd.
- `image_publisher` (string) PublisherName for your base image. See [documentation](https://azure.microsoft.com/en-us/documentation/articles/resource-groups-vm-searching/) for details.
@@ -54,6 +47,32 @@ builder.
- `location` (string) Azure datacenter in which your VM will build.
CLI example `azure location list`
+
+#### VHD or Managed Image
+
+The Azure builder can create either a VHD, or a managed image. When creating a VHD the following two options are required.
+
+- `capture_container_name` (string) Destination container name. Essentially the "directory" where your VHD will be
+ organized in Azure. The captured VHD's URL will be https://.blob.core.windows.net/system/Microsoft.Compute/Images//.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.vhd.
+
+- `capture_name_prefix` (string) VHD prefix. The final artifacts will be named `PREFIX-osDisk.UUID` and
+ `PREFIX-vmTemplate.UUID`.
+
+- `resource_group_name` (string) Resource group under which the final artifact will be stored.
+
+- `storage_account` (string) Storage account under which the final artifact will be stored.
+
+When creating a managed image the following two options are required.
+
+- `managed_image_name` (string) Specify the managed image name where the result of the Packer build will be saved. The
+ image name must not exist ahead of time, and will not be overwritten. If this value is set, the value
+ `managed_image_resource_group_name` must also be set. See [documentation](https://docs.microsoft.com/en-us/azure/storage/storage-managed-disks-overview#images)
+ to learn more about managed images.
+
+- `managed_image_resource_group_name` (string) Specify the managed image resource group name where the result of the Packer build will be
+ saved. The resource group must already exist. If this value is set, the value `managed_image_name` must also be
+ set. See [documentation](https://docs.microsoft.com/en-us/azure/storage/storage-managed-disks-overview#images) to
+ learn more about managed images.
### Optional:
@@ -89,16 +108,7 @@ builder.
- `image_url` (string) Specify a custom VHD to use. If this value is set, do not set image\_publisher, image\_offer,
image\_sku, or image\_version.
-- `managed_image_name` (string) Specify the managed image name where the result of the Packer build will be saved. The
- image name must not exist ahead of time, and will not be overwritten. If this value is set, the value
- `managed_image_resource_group_name` must also be set. See [documentation](https://docs.microsoft.com/en-us/azure/storage/storage-managed-disks-overview#images)
- to learn more about managed images.
-
-- `managed_image_resource_group_name` (string) Specify the managed image resource group name where the result of the Packer build will be
- saved. The resource group must already exist. If this value is set, the value `managed_image_name` must also be
- set. See [documentation](https://docs.microsoft.com/en-us/azure/storage/storage-managed-disks-overview#images) to
- learn more about managed images.
-
+
- `object_id` (string) Specify an OAuth Object ID to protect WinRM certificates
created at runtime. This variable is required when creating images based on
Windows; this variable is not used by non-Windows builds. See `Windows`