azure: fit and finish
* More unit testing to assert customer's configuration. * Further reduce the options that are needed to power an Azure build. This seems like a much more manageable level. * Update all of the examples to use a more current VM sku. * Add an example for RHEL. * Move from OpenSuSE to SuSE. * Update the docs.
This commit is contained in:
parent
51e03d39e6
commit
c09f8b84b9
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"))
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 }}'",
|
||||
|
|
|
@ -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 }}'",
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
},
|
||||
|
||||
"location": "West US",
|
||||
"vm_size": "Standard_A2"
|
||||
"vm_size": "Standard_DS2_v2"
|
||||
}
|
||||
],
|
||||
"provisioners": [{
|
||||
|
|
|
@ -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": [{
|
||||
|
|
|
@ -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
|
||||
}]
|
||||
}
|
|
@ -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 }}'",
|
|
@ -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 }}'",
|
||||
|
|
|
@ -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 }}'",
|
||||
|
|
|
@ -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 }}'",
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
"winrm_username": "packer",
|
||||
|
||||
"location": "West US",
|
||||
"vm_size": "Standard_A2"
|
||||
"vm_size": "Standard_DS2_v2"
|
||||
}],
|
||||
"provisioners": [{
|
||||
"type": "powershell",
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
},
|
||||
|
||||
"location": "West US",
|
||||
"vm_size": "Standard_A2"
|
||||
"vm_size": "Standard_DS2_v2"
|
||||
}
|
||||
],
|
||||
"provisioners": [{
|
||||
|
|
|
@ -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 <https://><storage_account>.blob.core.windows.net/system/Microsoft.Compute/Images/<capture_container_name>/<capture_name_prefix>.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://<storage_account>.blob.core.windows.net/system/Microsoft.Compute/Images/<capture_container_name>/<capture_name_prefix>.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://<storage_account>.blob.core.windows.net/system/Microsoft.Compute/Images/<capture_container_name>/<capture_name_prefix>.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`
|
||||
|
|
Loading…
Reference in New Issue