2016-03-04 05:14:55 -05:00
package arm
import (
2018-04-06 04:12:58 -04:00
"context"
2016-03-04 05:14:55 -05:00
"errors"
"fmt"
"log"
2017-06-27 16:19:21 -04:00
"os"
"runtime"
2016-06-30 19:51:52 -04:00
"strings"
2016-04-21 19:50:03 -04:00
"time"
2016-03-04 05:14:55 -05:00
2018-04-06 04:12:58 -04:00
armstorage "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage"
"github.com/Azure/azure-sdk-for-go/storage"
"github.com/Azure/go-autorest/autorest/adal"
2018-05-18 03:32:01 -04:00
"github.com/dgrijalva/jwt-go"
2019-12-17 05:25:56 -05:00
"github.com/hashicorp/hcl/v2/hcldec"
2018-05-18 15:09:42 -04:00
packerAzureCommon "github.com/hashicorp/packer/builder/azure/common"
2017-04-04 16:39:01 -04:00
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/builder/azure/common/lin"
packerCommon "github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
2018-01-19 19:18:44 -05:00
"github.com/hashicorp/packer/helper/multistep"
2017-04-04 16:39:01 -04:00
"github.com/hashicorp/packer/packer"
2016-03-04 05:14:55 -05:00
)
type Builder struct {
2019-12-17 05:25:56 -05:00
config Config
2019-03-22 09:53:28 -04:00
stateBag multistep . StateBag
runner multistep . Runner
2016-03-04 05:14:55 -05:00
}
const (
2018-04-06 04:12:58 -04:00
DefaultSasBlobContainer = "system/Microsoft.Compute"
DefaultSecretName = "packerKeyVaultSecret"
2016-03-04 05:14:55 -05:00
)
2019-12-17 05:25:56 -05:00
func ( b * Builder ) ConfigSpec ( ) hcldec . ObjectSpec { return b . config . FlatMapstructure ( ) . HCL2Spec ( ) }
2019-12-17 00:23:05 -05:00
func ( b * Builder ) Prepare ( raws ... interface { } ) ( [ ] string , [ ] string , error ) {
2019-12-17 05:25:56 -05:00
warnings , errs := b . config . Prepare ( raws ... )
2016-03-04 05:14:55 -05:00
if errs != nil {
2019-12-17 00:23:05 -05:00
return nil , warnings , errs
2016-03-04 05:14:55 -05:00
}
b . stateBag = new ( multistep . BasicStateBag )
2016-04-21 19:50:03 -04:00
b . configureStateBag ( b . stateBag )
b . setTemplateParameters ( b . stateBag )
2017-05-29 00:06:09 -04:00
b . setImageParameters ( b . stateBag )
2016-03-04 05:14:55 -05:00
2019-12-17 00:23:05 -05:00
return nil , warnings , errs
2016-03-04 05:14:55 -05:00
}
2019-03-22 09:53:28 -04:00
func ( b * Builder ) Run ( ctx context . Context , ui packer . Ui , hook packer . Hook ) ( packer . Artifact , error ) {
2018-05-18 03:32:01 -04:00
2016-06-22 19:04:13 -04:00
ui . Say ( "Running builder ..." )
2019-03-22 09:53:28 -04:00
ctx , cancel := context . WithCancel ( ctx )
2018-05-01 19:40:40 -04:00
defer cancel ( )
2019-09-25 13:16:17 -04:00
// FillParameters function captures authType and sets defaults.
2019-05-31 18:37:43 -04:00
err := b . config . ClientConfig . FillParameters ( )
if err != nil {
return nil , err
2016-06-22 19:04:13 -04:00
}
2016-03-04 05:14:55 -05:00
2016-04-29 18:02:28 -04:00
log . Print ( ":: Configuration" )
2019-12-17 05:25:56 -05:00
packerAzureCommon . DumpConfig ( & b . config , func ( s string ) { log . Print ( s ) } )
2016-04-29 18:02:28 -04:00
2016-03-04 05:14:55 -05:00
b . stateBag . Put ( "hook" , hook )
b . stateBag . Put ( constants . Ui , ui )
2016-04-21 19:50:03 -04:00
spnCloud , spnKeyVault , err := b . getServicePrincipalTokens ( ui . Say )
2016-03-04 05:14:55 -05:00
if err != nil {
return nil , err
}
ui . Message ( "Creating Azure Resource Manager (ARM) client ..." )
2016-04-21 19:50:03 -04:00
azureClient , err := NewAzureClient (
2019-05-31 18:37:43 -04:00
b . config . ClientConfig . SubscriptionID ,
2016-04-21 19:50:03 -04:00
b . config . ResourceGroupName ,
b . config . StorageAccount ,
2019-10-14 09:59:26 -04:00
b . config . ClientConfig . CloudEnvironment ( ) ,
2019-07-26 18:20:32 -04:00
b . config . SharedGalleryTimeout ,
2019-10-11 18:29:02 -04:00
b . config . PollingDurationTimeout ,
2016-04-21 19:50:03 -04:00
spnCloud ,
spnKeyVault )
2018-05-18 04:41:00 -04:00
2016-03-04 05:14:55 -05:00
if err != nil {
return nil , err
}
2016-06-30 19:51:52 -04:00
resolver := newResourceResolver ( azureClient )
2019-12-17 05:25:56 -05:00
if err := resolver . Resolve ( & b . config ) ; err != nil {
2016-06-30 19:51:52 -04:00
return nil , err
}
2019-05-31 18:37:43 -04:00
if b . config . ClientConfig . ObjectID == "" {
b . config . ClientConfig . ObjectID = getObjectIdFromToken ( ui , spnCloud )
2018-05-22 00:38:41 -04:00
} else {
ui . Message ( "You have provided Object_ID which is no longer needed, azure packer builder determines this dynamically from the authentication token" )
}
2018-05-18 03:32:01 -04:00
2019-05-31 18:37:43 -04:00
if b . config . ClientConfig . ObjectID == "" && b . config . OSType != constants . Target_Linux {
2018-05-22 00:38:41 -04:00
return nil , fmt . Errorf ( "could not determine the ObjectID for the user, which is required for Windows builds" )
2018-05-18 03:32:01 -04:00
}
2017-05-29 00:06:09 -04:00
if b . config . isManagedImage ( ) {
2018-05-01 19:40:40 -04:00
group , err := azureClient . GroupsClient . Get ( ctx , b . config . ManagedImageResourceGroupName )
2017-05-29 00:06:09 -04:00
if err != nil {
2017-05-30 14:25:46 -04:00
return nil , fmt . Errorf ( "Cannot locate the managed image resource group %s." , b . config . ManagedImageResourceGroupName )
2017-05-29 00:06:09 -04:00
}
2017-05-30 14:25:46 -04:00
b . config . manageImageLocation = * group . Location
2017-05-29 00:06:09 -04:00
// If a managed image already exists it cannot be overwritten.
2018-05-01 19:40:40 -04:00
_ , err = azureClient . ImagesClient . Get ( ctx , b . config . ManagedImageResourceGroupName , b . config . ManagedImageName , "" )
2017-05-29 00:06:09 -04:00
if err == nil {
2018-03-10 13:17:38 -05:00
if b . config . PackerForce {
ui . Say ( fmt . Sprintf ( "the managed image named %s already exists, but deleting it due to -force flag" , b . config . ManagedImageName ) )
2018-05-01 19:40:40 -04:00
f , err := azureClient . ImagesClient . Delete ( ctx , b . config . ManagedImageResourceGroupName , b . config . ManagedImageName )
2018-04-06 04:12:58 -04:00
if err == nil {
2019-05-30 17:25:43 -04:00
err = f . WaitForCompletionRef ( ctx , azureClient . ImagesClient . Client )
2018-04-06 04:12:58 -04:00
}
2018-03-10 13:17:38 -05:00
if err != nil {
return nil , fmt . Errorf ( "failed to delete the managed image named %s : %s" , b . config . ManagedImageName , azureClient . LastError . Error ( ) )
}
} else {
return nil , fmt . Errorf ( "the managed image named %s already exists in the resource group %s, use the -force option to automatically delete it." , b . config . ManagedImageName , b . config . ManagedImageResourceGroupName )
}
2017-05-29 00:06:09 -04:00
}
2018-05-10 16:15:35 -04:00
} else {
// User is not using Managed Images to build, warning message here that this path is being deprecated
ui . Error ( "Warning: You are using Azure Packer Builder to create VHDs which is being deprecated, consider using Managed Images. Learn more http://aka.ms/packermanagedimage" )
2017-05-29 00:06:09 -04:00
}
2017-11-30 19:43:35 -05:00
if b . config . BuildResourceGroupName != "" {
2018-05-01 19:40:40 -04:00
group , err := azureClient . GroupsClient . Get ( ctx , b . config . BuildResourceGroupName )
2017-11-30 19:43:35 -05:00
if err != nil {
return nil , fmt . Errorf ( "Cannot locate the existing build resource resource group %s." , b . config . BuildResourceGroupName )
}
b . config . Location = * group . Location
}
2019-02-15 10:24:19 -05:00
b . config . validateLocationZoneResiliency ( ui . Say )
2017-06-07 18:01:10 -04:00
if b . config . StorageAccount != "" {
2018-05-01 19:40:40 -04:00
account , err := b . getBlobAccount ( ctx , azureClient , b . config . ResourceGroupName , b . config . StorageAccount )
2017-06-07 18:01:10 -04:00
if err != nil {
return nil , err
}
b . config . storageAccountBlobEndpoint = * account . AccountProperties . PrimaryEndpoints . Blob
2017-05-29 00:06:09 -04:00
2017-06-07 18:01:10 -04:00
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 )
}
2017-05-29 00:06:09 -04:00
}
2016-04-21 19:50:03 -04:00
2016-06-30 19:51:52 -04:00
endpointConnectType := PublicEndpoint
2017-08-06 18:32:44 -04:00
if b . isPublicPrivateNetworkCommunication ( ) && b . isPrivateNetworkCommunication ( ) {
endpointConnectType = PublicEndpointInPrivateNetwork
} else if b . isPrivateNetworkCommunication ( ) {
2016-06-30 19:51:52 -04:00
endpointConnectType = PrivateEndpoint
}
2017-05-29 00:06:09 -04:00
b . setRuntimeParameters ( b . stateBag )
2016-04-21 19:50:03 -04:00
b . setTemplateParameters ( b . stateBag )
2017-05-29 00:06:09 -04:00
b . setImageParameters ( b . stateBag )
2016-04-21 19:50:03 -04:00
2017-11-30 03:11:17 -05:00
deploymentName := b . stateBag . Get ( constants . ArmDeploymentName ) . ( string )
2019-06-19 02:10:18 -04:00
// For Managed Images, validate that Shared Gallery Image exists before publishing to SIG
if b . config . isManagedImage ( ) && b . config . SharedGalleryDestination . SigDestinationGalleryName != "" {
_ , err = azureClient . GalleryImagesClient . Get ( ctx , b . config . SharedGalleryDestination . SigDestinationResourceGroup , b . config . SharedGalleryDestination . SigDestinationGalleryName , b . config . SharedGalleryDestination . SigDestinationImageName )
if err != nil {
2019-06-24 12:57:07 -04:00
return nil , fmt . Errorf ( "the Shared Gallery Image to which to publish the managed image version to does not exist in the resource group %s" , b . config . SharedGalleryDestination . SigDestinationResourceGroup )
2019-06-19 02:10:18 -04:00
}
// SIG requires that replication regions include the region in which the Managed Image resides
managedImageLocation := normalizeAzureRegion ( b . stateBag . Get ( constants . ArmLocation ) . ( string ) )
foundMandatoryReplicationRegion := false
var normalizedReplicationRegions [ ] string
for _ , region := range b . config . SharedGalleryDestination . SigDestinationReplicationRegions {
// change region to lower-case and strip spaces
normalizedRegion := normalizeAzureRegion ( region )
normalizedReplicationRegions = append ( normalizedReplicationRegions , normalizedRegion )
if strings . EqualFold ( normalizedRegion , managedImageLocation ) {
foundMandatoryReplicationRegion = true
continue
}
}
if foundMandatoryReplicationRegion == false {
b . config . SharedGalleryDestination . SigDestinationReplicationRegions = append ( normalizedReplicationRegions , managedImageLocation )
}
b . stateBag . Put ( constants . ArmManagedImageSharedGalleryReplicationRegions , b . config . SharedGalleryDestination . SigDestinationReplicationRegions )
}
builder/azure-arm: Set WinRMPassword on the communicator config
Build results before change
```
azure-arm: output will be in this color.
==> azure-arm: Running builder ...
azure-arm:
==> azure-arm: Provisioning with Powershell...
==> azure-arm: Provisioning with powershell script:
/tmp/powershell-provisioner922851060
==> azure-arm: Exception calling "RegisterTaskDefinition" with "7" argument(s): "(38,4):Task:"
==> azure-arm: At C:\Windows\Temp\packer-elevated-shell-5e320d29-bdbd-b619-9e64-0c8a301b9d1d.p
==> azure-arm: s1:60 char:1 ==> azure-arm: + $f.RegisterTaskDefinition($name, $t, 6,
"packer", $password, $logon_type,
==> azure-arm: $null) ...
==> azure-arm: +
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
==> azure-arm: ~~~
==> azure-arm: + CategoryInfo : NotSpecified:
(:) [], MethodInvocationException
==> azure-arm: + FullyQualifiedErrorId :
ComMethodTargetInvocation
==> azure-arm:
==> azure-arm: Exception calling "GetTask" with "1"
argument(s): "The system cannot find the
==> azure-arm: file specified. (Exception from HRESULT:
0x80070002)"
==> azure-arm: At
C:\Windows\Temp\packer-elevated-shell-5e320d29-bdbd-b619-9e64-0c8a301b9d1d.p
==> azure-arm: s1:61 char:1
==> azure-arm: + $t = $f.GetTask("\$name")
==> azure-arm: + ~~~~~~~~~~~~~~~~~~~~~~~~~
==> azure-arm: + CategoryInfo : NotSpecified:
(:) [], MethodInvocationException
==> azure-arm: + FullyQualifiedErrorId :
ComMethodTargetInvocation
==> azure-arm:
==> azure-arm: Method invocation failed because
[System.__ComObject] does not contain a
==> azure-arm: method named 'Run'.
==> azure-arm: At
C:\Windows\Temp\packer-elevated-shell-5e320d29-bdbd-b619-9e64-0c8a301b9d1d.p
==> azure-arm: s1:62 char:1
==> azure-arm: + $t.Run($null) | Out-Null
==> azure-arm: + ~~~~~~~~~~~~~~~~~~~~~~~~
==> azure-arm: + CategoryInfo :
InvalidOperation: (Run:String) [], RuntimeExcept
==> azure-arm: ion
==> azure-arm: + FullyQualifiedErrorId : MethodNotFound
==> azure-arm:
Cancelling build after receiving interrupt
==> azure-arm: Removing the created Deployment object:
'pkrdp087bb80ibj'
==> azure-arm: Removing the created Deployment object:
'kvpkrdp087bb80ibj'
==> azure-arm:
==> azure-arm: Cleanup requested, deleting resource group
...
==> azure-arm: Resource group has been deleted.
Build 'azure-arm' errored: Build was cancelled.
Cleanly cancelled builds after being interrupted.
```
Build results after change
```
azure-arm: WinRM connected.
==> azure-arm: <Objs Version="1.1.0.1"
xmlns="http://schemas.microsoft.com/powershell/2004/04"><Obj S="progress" RefId="0"><TN RefId="0"><T>System.Management.Automation.PSCustomObject</T><T>System.Object</T></TN><MS><I64
N="SourceId">1</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj><Obj S="progress" RefId="1"><TNRef RefId="0" /><MS><I64 N="SourceId">2</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj><Obj S="progress" RefId="2"><TNRef RefId="0" /><MS><I64 N="SourceId">3</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj></Objs>
==> azure-arm: Connected to WinRM!
==> azure-arm: Running local shell script:
/tmp/packer-shell091779215 azure-arm: 022xUtbwAH3DdqIoRCOh9caZi8tOYqcY
==> azure-arm: Provisioning with Powershell...
==> azure-arm: Provisioning with powershell script: /tmp/powershell-provisioner469853889
azure-arm: HELLO NEW USER; automatically generated aws password is: 022xUtbwAH3DdqIoRCOh9caZi8tOYqcY
==> azure-arm: Querying the machine's properties ...
```
2020-01-29 14:54:42 -05:00
var steps [ ] multistep . Step
2016-10-12 20:54:59 -04:00
if b . config . OSType == constants . Target_Linux {
2018-11-06 14:17:03 -05:00
steps = [ ] multistep . Step {
NewStepCreateResourceGroup ( azureClient , ui ) ,
2019-12-17 05:25:56 -05:00
NewStepValidateTemplate ( azureClient , ui , & b . config , GetVirtualMachineDeployment ) ,
NewStepDeployTemplate ( azureClient , ui , & b . config , deploymentName , GetVirtualMachineDeployment ) ,
2018-11-06 14:17:03 -05:00
NewStepGetIPAddress ( azureClient , ui , endpointConnectType ) ,
& communicator . StepConnectSSH {
Config : & b . config . Comm ,
Host : lin . SSHHost ,
SSHConfig : b . config . Comm . SSHConfigFunc ( ) ,
} ,
& packerCommon . StepProvision { } ,
& packerCommon . StepCleanupTempKeys {
Comm : & b . config . Comm ,
} ,
NewStepGetOSDisk ( azureClient , ui ) ,
NewStepGetAdditionalDisks ( azureClient , ui ) ,
NewStepPowerOffCompute ( azureClient , ui ) ,
2019-12-17 05:25:56 -05:00
NewStepSnapshotOSDisk ( azureClient , ui , & b . config ) ,
NewStepSnapshotDataDisks ( azureClient , ui , & b . config ) ,
2018-11-06 14:17:03 -05:00
NewStepCaptureImage ( azureClient , ui ) ,
2019-12-17 05:25:56 -05:00
NewStepPublishToSharedImageGallery ( azureClient , ui , & b . config ) ,
2018-11-06 14:17:03 -05:00
NewStepDeleteResourceGroup ( azureClient , ui ) ,
NewStepDeleteOSDisk ( azureClient , ui ) ,
NewStepDeleteAdditionalDisks ( azureClient , ui ) ,
2018-11-13 20:47:48 -05:00
}
2016-10-12 20:54:59 -04:00
} else if b . config . OSType == constants . Target_Windows {
2017-11-30 03:11:17 -05:00
keyVaultDeploymentName := b . stateBag . Get ( constants . ArmKeyVaultDeploymentName ) . ( string )
2018-11-06 14:17:03 -05:00
steps = [ ] multistep . Step {
2016-04-21 19:50:03 -04:00
NewStepCreateResourceGroup ( azureClient , ui ) ,
2019-12-17 05:25:56 -05:00
NewStepValidateTemplate ( azureClient , ui , & b . config , GetKeyVaultDeployment ) ,
NewStepDeployTemplate ( azureClient , ui , & b . config , keyVaultDeploymentName , GetKeyVaultDeployment ) ,
2016-04-21 19:50:03 -04:00
NewStepGetCertificate ( azureClient , ui ) ,
2019-12-17 05:25:56 -05:00
NewStepSetCertificate ( & b . config , ui ) ,
NewStepValidateTemplate ( azureClient , ui , & b . config , GetVirtualMachineDeployment ) ,
NewStepDeployTemplate ( azureClient , ui , & b . config , deploymentName , GetVirtualMachineDeployment ) ,
2016-06-30 19:51:52 -04:00
NewStepGetIPAddress ( azureClient , ui , endpointConnectType ) ,
2016-04-21 19:50:03 -04:00
& communicator . StepConnectWinRM {
Config : & b . config . Comm ,
Host : func ( stateBag multistep . StateBag ) ( string , error ) {
return stateBag . Get ( constants . SSHHost ) . ( string ) , nil
} ,
WinRMConfig : func ( multistep . StateBag ) ( * communicator . WinRMConfig , error ) {
return & communicator . WinRMConfig {
Username : b . config . UserName ,
builder/azure-arm: Set WinRMPassword on the communicator config
Build results before change
```
azure-arm: output will be in this color.
==> azure-arm: Running builder ...
azure-arm:
==> azure-arm: Provisioning with Powershell...
==> azure-arm: Provisioning with powershell script:
/tmp/powershell-provisioner922851060
==> azure-arm: Exception calling "RegisterTaskDefinition" with "7" argument(s): "(38,4):Task:"
==> azure-arm: At C:\Windows\Temp\packer-elevated-shell-5e320d29-bdbd-b619-9e64-0c8a301b9d1d.p
==> azure-arm: s1:60 char:1 ==> azure-arm: + $f.RegisterTaskDefinition($name, $t, 6,
"packer", $password, $logon_type,
==> azure-arm: $null) ...
==> azure-arm: +
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
==> azure-arm: ~~~
==> azure-arm: + CategoryInfo : NotSpecified:
(:) [], MethodInvocationException
==> azure-arm: + FullyQualifiedErrorId :
ComMethodTargetInvocation
==> azure-arm:
==> azure-arm: Exception calling "GetTask" with "1"
argument(s): "The system cannot find the
==> azure-arm: file specified. (Exception from HRESULT:
0x80070002)"
==> azure-arm: At
C:\Windows\Temp\packer-elevated-shell-5e320d29-bdbd-b619-9e64-0c8a301b9d1d.p
==> azure-arm: s1:61 char:1
==> azure-arm: + $t = $f.GetTask("\$name")
==> azure-arm: + ~~~~~~~~~~~~~~~~~~~~~~~~~
==> azure-arm: + CategoryInfo : NotSpecified:
(:) [], MethodInvocationException
==> azure-arm: + FullyQualifiedErrorId :
ComMethodTargetInvocation
==> azure-arm:
==> azure-arm: Method invocation failed because
[System.__ComObject] does not contain a
==> azure-arm: method named 'Run'.
==> azure-arm: At
C:\Windows\Temp\packer-elevated-shell-5e320d29-bdbd-b619-9e64-0c8a301b9d1d.p
==> azure-arm: s1:62 char:1
==> azure-arm: + $t.Run($null) | Out-Null
==> azure-arm: + ~~~~~~~~~~~~~~~~~~~~~~~~
==> azure-arm: + CategoryInfo :
InvalidOperation: (Run:String) [], RuntimeExcept
==> azure-arm: ion
==> azure-arm: + FullyQualifiedErrorId : MethodNotFound
==> azure-arm:
Cancelling build after receiving interrupt
==> azure-arm: Removing the created Deployment object:
'pkrdp087bb80ibj'
==> azure-arm: Removing the created Deployment object:
'kvpkrdp087bb80ibj'
==> azure-arm:
==> azure-arm: Cleanup requested, deleting resource group
...
==> azure-arm: Resource group has been deleted.
Build 'azure-arm' errored: Build was cancelled.
Cleanly cancelled builds after being interrupted.
```
Build results after change
```
azure-arm: WinRM connected.
==> azure-arm: <Objs Version="1.1.0.1"
xmlns="http://schemas.microsoft.com/powershell/2004/04"><Obj S="progress" RefId="0"><TN RefId="0"><T>System.Management.Automation.PSCustomObject</T><T>System.Object</T></TN><MS><I64
N="SourceId">1</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj><Obj S="progress" RefId="1"><TNRef RefId="0" /><MS><I64 N="SourceId">2</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj><Obj S="progress" RefId="2"><TNRef RefId="0" /><MS><I64 N="SourceId">3</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj></Objs>
==> azure-arm: Connected to WinRM!
==> azure-arm: Running local shell script:
/tmp/packer-shell091779215 azure-arm: 022xUtbwAH3DdqIoRCOh9caZi8tOYqcY
==> azure-arm: Provisioning with Powershell...
==> azure-arm: Provisioning with powershell script: /tmp/powershell-provisioner469853889
azure-arm: HELLO NEW USER; automatically generated aws password is: 022xUtbwAH3DdqIoRCOh9caZi8tOYqcY
==> azure-arm: Querying the machine's properties ...
```
2020-01-29 14:54:42 -05:00
Password : b . config . Comm . WinRMPassword ,
2016-04-21 19:50:03 -04:00
} , nil
} ,
} ,
2016-04-29 18:02:28 -04:00
& packerCommon . StepProvision { } ,
2016-04-21 19:50:03 -04:00
NewStepGetOSDisk ( azureClient , ui ) ,
2018-02-23 18:34:13 -05:00
NewStepGetAdditionalDisks ( azureClient , ui ) ,
2019-04-01 13:49:11 -04:00
NewStepPowerOffCompute ( azureClient , ui ) ,
2019-12-17 05:25:56 -05:00
NewStepSnapshotOSDisk ( azureClient , ui , & b . config ) ,
NewStepSnapshotDataDisks ( azureClient , ui , & b . config ) ,
2016-04-21 19:50:03 -04:00
NewStepCaptureImage ( azureClient , ui ) ,
2019-12-17 05:25:56 -05:00
NewStepPublishToSharedImageGallery ( azureClient , ui , & b . config ) ,
2016-04-21 19:50:03 -04:00
NewStepDeleteResourceGroup ( azureClient , ui ) ,
NewStepDeleteOSDisk ( azureClient , ui ) ,
2018-02-23 18:34:13 -05:00
NewStepDeleteAdditionalDisks ( azureClient , ui ) ,
2018-11-13 20:47:48 -05:00
}
2018-11-06 14:17:03 -05:00
} else {
return nil , fmt . Errorf ( "Builder does not support the os_type '%s'" , b . config . OSType )
2016-03-04 05:14:55 -05:00
}
if b . config . PackerDebug {
ui . Message ( fmt . Sprintf ( "temp admin user: '%s'" , b . config . UserName ) )
ui . Message ( fmt . Sprintf ( "temp admin password: '%s'" , b . config . Password ) )
2017-06-26 16:44:34 -04:00
2018-08-24 03:17:47 -04:00
if len ( b . config . Comm . SSHPrivateKey ) != 0 {
2017-06-27 16:19:21 -04:00
debugKeyPath := fmt . Sprintf ( "%s-%s.pem" , b . config . PackerBuildName , b . config . tmpComputeName )
ui . Message ( fmt . Sprintf ( "temp ssh key: %s" , debugKeyPath ) )
b . writeSSHPrivateKey ( ui , debugKeyPath )
2017-06-26 16:44:34 -04:00
}
2016-03-04 05:14:55 -05:00
}
2016-09-13 20:04:18 -04:00
b . runner = packerCommon . NewRunner ( steps , b . config . PackerConfig , ui )
2019-03-22 09:53:28 -04:00
b . runner . Run ( ctx , b . stateBag )
2016-03-04 05:14:55 -05:00
// Report any errors.
if rawErr , ok := b . stateBag . GetOk ( constants . Error ) ; ok {
return nil , rawErr . ( error )
}
// If we were interrupted or cancelled, then just exit.
if _ , ok := b . stateBag . GetOk ( multistep . StateCancelled ) ; ok {
return nil , errors . New ( "Build was cancelled." )
}
if _ , ok := b . stateBag . GetOk ( multistep . StateHalted ) ; ok {
return nil , errors . New ( "Build was halted." )
}
2020-01-30 05:27:58 -05:00
generatedData := map [ string ] interface { } { "generated_data" : b . stateBag . Get ( "generated_data" ) }
2017-06-07 18:01:10 -04:00
if b . config . isManagedImage ( ) {
2019-05-31 18:37:43 -04:00
managedImageID := fmt . Sprintf ( "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/images/%s" ,
b . config . ClientConfig . SubscriptionID , b . config . ManagedImageResourceGroupName , b . config . ManagedImageName )
2019-07-03 20:44:05 -04:00
if b . config . SharedGalleryDestination . SigDestinationGalleryName != "" {
2020-01-30 05:27:58 -05:00
return NewManagedImageArtifactWithSIGAsDestination ( b . config . OSType ,
b . config . ManagedImageResourceGroupName ,
b . config . ManagedImageName ,
b . config . manageImageLocation ,
managedImageID ,
b . config . ManagedImageOSDiskSnapshotName ,
b . config . ManagedImageDataDiskSnapshotPrefix ,
b . stateBag . Get ( constants . ArmManagedImageSharedGalleryId ) . ( string ) ,
generatedData )
2019-07-03 20:44:05 -04:00
}
2020-01-30 05:27:58 -05:00
return NewManagedImageArtifact ( b . config . OSType ,
b . config . ManagedImageResourceGroupName ,
b . config . ManagedImageName ,
b . config . manageImageLocation ,
managedImageID ,
b . config . ManagedImageOSDiskSnapshotName ,
b . config . ManagedImageDataDiskSnapshotPrefix ,
generatedData )
2017-06-07 18:01:10 -04:00
} else if template , ok := b . stateBag . GetOk ( constants . ArmCaptureTemplate ) ; ok {
2016-04-21 19:50:03 -04:00
return NewArtifact (
template . ( * CaptureTemplate ) ,
func ( name string ) string {
2017-05-28 03:38:45 -04:00
blob := azureClient . BlobStorageClient . GetContainerReference ( DefaultSasBlobContainer ) . GetBlobReference ( name )
2018-04-06 04:12:58 -04:00
options := storage . BlobSASOptions { }
options . BlobServiceSASPermissions . Read = true
options . Expiry = time . Now ( ) . AddDate ( 0 , 1 , 0 ) . UTC ( ) // one month
sasUrl , _ := blob . GetSASURI ( options )
2016-04-21 19:50:03 -04:00
return sasUrl
2018-08-08 11:04:28 -04:00
} ,
2020-01-30 05:27:58 -05:00
b . config . OSType ,
generatedData )
2016-04-21 19:50:03 -04:00
}
2020-01-30 05:27:58 -05:00
return & Artifact {
StateData : generatedData ,
} , nil
2016-03-04 05:14:55 -05:00
}
2017-06-27 16:19:21 -04:00
func ( b * Builder ) writeSSHPrivateKey ( ui packer . Ui , debugKeyPath string ) {
f , err := os . Create ( debugKeyPath )
if err != nil {
ui . Say ( fmt . Sprintf ( "Error saving debug key: %s" , err ) )
}
defer f . Close ( )
// Write the key out
2018-08-24 03:17:47 -04:00
if _ , err := f . Write ( b . config . Comm . SSHPrivateKey ) ; err != nil {
2017-06-27 16:19:21 -04:00
ui . Say ( fmt . Sprintf ( "Error saving debug key: %s" , err ) )
return
}
// Chmod it so that it is SSH ready
if runtime . GOOS != "windows" {
if err := f . Chmod ( 0600 ) ; err != nil {
ui . Say ( fmt . Sprintf ( "Error setting permissions of debug key: %s" , err ) )
}
}
}
2017-08-06 18:32:44 -04:00
func ( b * Builder ) isPublicPrivateNetworkCommunication ( ) bool {
return DefaultPrivateVirtualNetworkWithPublicIp != b . config . PrivateVirtualNetworkWithPublicIp
}
2016-06-30 19:51:52 -04:00
func ( b * Builder ) isPrivateNetworkCommunication ( ) bool {
return b . config . VirtualNetworkName != ""
}
2017-05-29 00:06:09 -04:00
func equalLocation ( location1 , location2 string ) bool {
return strings . EqualFold ( canonicalizeLocation ( location1 ) , canonicalizeLocation ( location2 ) )
}
func canonicalizeLocation ( location string ) string {
return strings . Replace ( location , " " , "" , - 1 )
}
2018-05-01 19:40:40 -04:00
func ( b * Builder ) getBlobAccount ( ctx context . Context , client * AzureClient , resourceGroupName string , storageAccountName string ) ( * armstorage . Account , error ) {
account , err := client . AccountsClient . GetProperties ( ctx , resourceGroupName , storageAccountName )
2016-04-21 19:50:03 -04:00
if err != nil {
2017-05-29 00:06:09 -04:00
return nil , err
2016-04-21 19:50:03 -04:00
}
2017-05-29 00:06:09 -04:00
return & account , err
2016-04-21 19:50:03 -04:00
}
func ( b * Builder ) configureStateBag ( stateBag multistep . StateBag ) {
2016-03-04 05:14:55 -05:00
stateBag . Put ( constants . AuthorizedKey , b . config . sshAuthorizedKey )
2018-04-11 11:25:33 -04:00
stateBag . Put ( constants . ArmTags , b . config . AzureTags )
2016-03-04 05:14:55 -05:00
stateBag . Put ( constants . ArmComputeName , b . config . tmpComputeName )
stateBag . Put ( constants . ArmDeploymentName , b . config . tmpDeploymentName )
2017-11-30 03:11:17 -05:00
if b . config . OSType == constants . Target_Windows {
stateBag . Put ( constants . ArmKeyVaultDeploymentName , fmt . Sprintf ( "kv%s" , b . config . tmpDeploymentName ) )
}
2016-04-21 19:50:03 -04:00
stateBag . Put ( constants . ArmKeyVaultName , b . config . tmpKeyVaultName )
2018-03-10 14:17:43 -05:00
stateBag . Put ( constants . ArmNicName , b . config . tmpNicName )
stateBag . Put ( constants . ArmPublicIPAddressName , b . config . tmpPublicIPAddressName )
2017-11-09 06:20:09 -05:00
if b . config . TempResourceGroupName != "" && b . config . BuildResourceGroupName != "" {
stateBag . Put ( constants . ArmDoubleResourceGroupNameSet , true )
}
if b . config . tmpResourceGroupName != "" {
stateBag . Put ( constants . ArmResourceGroupName , b . config . tmpResourceGroupName )
stateBag . Put ( constants . ArmIsExistingResourceGroup , false )
} else {
stateBag . Put ( constants . ArmResourceGroupName , b . config . BuildResourceGroupName )
stateBag . Put ( constants . ArmIsExistingResourceGroup , true )
}
2016-04-21 19:50:03 -04:00
stateBag . Put ( constants . ArmStorageAccountName , b . config . StorageAccount )
2017-05-29 00:06:09 -04:00
stateBag . Put ( constants . ArmIsManagedImage , b . config . isManagedImage ( ) )
2017-05-30 14:25:46 -04:00
stateBag . Put ( constants . ArmManagedImageResourceGroupName , b . config . ManagedImageResourceGroupName )
stateBag . Put ( constants . ArmManagedImageName , b . config . ManagedImageName )
2018-11-05 18:48:22 -05:00
stateBag . Put ( constants . ArmManagedImageOSDiskSnapshotName , b . config . ManagedImageOSDiskSnapshotName )
stateBag . Put ( constants . ArmManagedImageDataDiskSnapshotPrefix , b . config . ManagedImageDataDiskSnapshotPrefix )
2018-05-15 14:41:26 -04:00
stateBag . Put ( constants . ArmAsyncResourceGroupDelete , b . config . AsyncResourceGroupDelete )
2019-06-18 01:34:26 -04:00
if b . config . isManagedImage ( ) && b . config . SharedGalleryDestination . SigDestinationGalleryName != "" {
2019-06-14 17:54:27 -04:00
stateBag . Put ( constants . ArmManagedImageSigPublishResourceGroup , b . config . SharedGalleryDestination . SigDestinationResourceGroup )
stateBag . Put ( constants . ArmManagedImageSharedGalleryName , b . config . SharedGalleryDestination . SigDestinationGalleryName )
stateBag . Put ( constants . ArmManagedImageSharedGalleryImageName , b . config . SharedGalleryDestination . SigDestinationImageName )
stateBag . Put ( constants . ArmManagedImageSharedGalleryImageVersion , b . config . SharedGalleryDestination . SigDestinationImageVersion )
2019-05-31 18:37:43 -04:00
stateBag . Put ( constants . ArmManagedImageSubscription , b . config . ClientConfig . SubscriptionID )
2020-01-02 02:23:04 -05:00
stateBag . Put ( constants . ArmManagedImageSharedGalleryImageVersionEndOfLifeDate , b . config . SharedGalleryImageVersionEndOfLifeDate )
stateBag . Put ( constants . ArmManagedImageSharedGalleryImageVersionReplicaCount , b . config . SharedGalleryImageVersionReplicaCount )
stateBag . Put ( constants . ArmManagedImageSharedGalleryImageVersionExcludeFromLatest , b . config . SharedGalleryImageVersionExcludeFromLatest )
2019-06-14 17:54:27 -04:00
}
2017-05-29 00:06:09 -04:00
}
// Parameters that are only known at runtime after querying Azure.
func ( b * Builder ) setRuntimeParameters ( stateBag multistep . StateBag ) {
2017-11-30 19:43:35 -05:00
stateBag . Put ( constants . ArmLocation , b . config . Location )
2017-05-30 14:25:46 -04:00
stateBag . Put ( constants . ArmManagedImageLocation , b . config . manageImageLocation )
2016-04-21 19:50:03 -04:00
}
func ( b * Builder ) setTemplateParameters ( stateBag multistep . StateBag ) {
2016-03-04 05:14:55 -05:00
stateBag . Put ( constants . ArmVirtualMachineCaptureParameters , b . config . toVirtualMachineCaptureParameters ( ) )
2016-04-21 19:50:03 -04:00
}
2016-03-04 05:14:55 -05:00
2017-05-29 00:06:09 -04:00
func ( b * Builder ) setImageParameters ( stateBag multistep . StateBag ) {
stateBag . Put ( constants . ArmImageParameters , b . config . toImageParameters ( ) )
}
2017-05-28 03:38:45 -04:00
func ( b * Builder ) getServicePrincipalTokens ( say func ( string ) ) ( * adal . ServicePrincipalToken , * adal . ServicePrincipalToken , error ) {
2019-05-31 18:37:43 -04:00
return b . config . ClientConfig . GetServicePrincipalTokens ( say )
2016-03-04 05:14:55 -05:00
}
2018-05-18 18:21:49 -04:00
2018-05-22 01:20:36 -04:00
func getObjectIdFromToken ( ui packer . Ui , token * adal . ServicePrincipalToken ) string {
2018-05-18 18:21:49 -04:00
claims := jwt . MapClaims { }
var p jwt . Parser
var err error
_ , _ , err = p . ParseUnverified ( token . OAuthToken ( ) , claims )
if err != nil {
2018-05-22 01:20:36 -04:00
ui . Error ( fmt . Sprintf ( "Failed to parse the token,Error: %s" , err . Error ( ) ) )
2018-05-18 18:21:49 -04:00
return ""
}
2019-08-29 04:34:59 -04:00
oid , _ := claims [ "oid" ] . ( string )
return oid
2018-05-18 18:21:49 -04:00
}
2019-06-18 01:34:26 -04:00
2019-06-18 02:01:22 -04:00
func normalizeAzureRegion ( name string ) string {
return strings . ToLower ( strings . Replace ( name , " " , "" , - 1 ) )
}