diff --git a/builder/azure/arm/artifact.go b/builder/azure/arm/artifact.go index f9bb25d81..f0c9c1070 100644 --- a/builder/azure/arm/artifact.go +++ b/builder/azure/arm/artifact.go @@ -35,12 +35,13 @@ type Artifact struct { ManagedImageId string ManagedImageOSDiskSnapshotName string ManagedImageDataDiskSnapshotPrefix string + ManagedImageSharedImageGalleryId string // Additional Disks AdditionalDisks *[]AdditionalDiskArtifact } -func NewManagedImageArtifact(osType, resourceGroup, name, location, id, osDiskSnapshotName, dataDiskSnapshotPrefix string) (*Artifact, error) { +func NewManagedImageArtifact(osType, resourceGroup, name, location, id, osDiskSnapshotName, dataDiskSnapshotPrefix, destinationSharedImageGalleryId string) (*Artifact, error) { return &Artifact{ ManagedImageResourceGroupName: resourceGroup, ManagedImageName: name, @@ -49,6 +50,7 @@ func NewManagedImageArtifact(osType, resourceGroup, name, location, id, osDiskSn OSType: osType, ManagedImageOSDiskSnapshotName: osDiskSnapshotName, ManagedImageDataDiskSnapshotPrefix: dataDiskSnapshotPrefix, + ManagedImageSharedImageGalleryId: destinationSharedImageGalleryId, }, nil } @@ -168,6 +170,9 @@ func (a *Artifact) String() string { if a.ManagedImageDataDiskSnapshotPrefix != "" { buf.WriteString(fmt.Sprintf("ManagedImageDataDiskSnapshotPrefix: %s\n", a.ManagedImageDataDiskSnapshotPrefix)) } + if a.ManagedImageSharedImageGalleryId != "" { + buf.WriteString(fmt.Sprintf("ManagedImageSharedImageGalleryId: %s\n", a.ManagedImageSharedImageGalleryId)) + } } else { buf.WriteString(fmt.Sprintf("StorageAccountLocation: %s\n", a.StorageAccountLocation)) buf.WriteString(fmt.Sprintf("OSDiskUri: %s\n", a.OSDiskUri)) diff --git a/builder/azure/arm/artifact_test.go b/builder/azure/arm/artifact_test.go index 11b8c3b2a..e73e14528 100644 --- a/builder/azure/arm/artifact_test.go +++ b/builder/azure/arm/artifact_test.go @@ -42,7 +42,7 @@ func TestArtifactIdVHD(t *testing.T) { } func TestArtifactIDManagedImage(t *testing.T) { - artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "fakeOsDiskSnapshotName", "fakeDataDiskSnapshotPrefix") + artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "fakeOsDiskSnapshotName", "fakeDataDiskSnapshotPrefix", "fakeSharedImageGalleryId") if err != nil { t.Fatalf("err=%s", err) } @@ -56,6 +56,7 @@ ManagedImageId: fakeID ManagedImageLocation: fakeLocation ManagedImageOSDiskSnapshotName: fakeOsDiskSnapshotName ManagedImageDataDiskSnapshotPrefix: fakeDataDiskSnapshotPrefix +ManagedImageSharedImageGalleryId: fakeSharedImageGalleryId ` result := artifact.String() @@ -65,7 +66,7 @@ ManagedImageDataDiskSnapshotPrefix: fakeDataDiskSnapshotPrefix } func TestArtifactIDManagedImageWithoutOSDiskSnapshotName(t *testing.T) { - artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "", "fakeDataDiskSnapshotPrefix") + artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "", "fakeDataDiskSnapshotPrefix", "fakeSharedImageGalleryId") if err != nil { t.Fatalf("err=%s", err) } @@ -78,6 +79,7 @@ ManagedImageName: fakeName ManagedImageId: fakeID ManagedImageLocation: fakeLocation ManagedImageDataDiskSnapshotPrefix: fakeDataDiskSnapshotPrefix +ManagedImageSharedImageGalleryId: fakeSharedImageGalleryId ` result := artifact.String() @@ -87,7 +89,7 @@ ManagedImageDataDiskSnapshotPrefix: fakeDataDiskSnapshotPrefix } func TestArtifactIDManagedImageWithoutDataDiskSnapshotPrefix(t *testing.T) { - artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "fakeOsDiskSnapshotName", "") + artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "fakeOsDiskSnapshotName", "", "fakeSharedImageGalleryId") if err != nil { t.Fatalf("err=%s", err) } @@ -100,6 +102,30 @@ ManagedImageName: fakeName ManagedImageId: fakeID ManagedImageLocation: fakeLocation ManagedImageOSDiskSnapshotName: fakeOsDiskSnapshotName +ManagedImageSharedImageGalleryId: fakeSharedImageGalleryId +` + + result := artifact.String() + if result != expected { + t.Fatalf("bad: %s", result) + } +} + +func TestArtifactIDManagedImageWithoutSharedImageGalleryId(t *testing.T) { + artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "fakeOsDiskSnapshotName", "fakeDataDiskSnapshotPrefix", "") + if err != nil { + t.Fatalf("err=%s", err) + } + + expected := `Azure.ResourceManagement.VMImage: + +OSType: Linux +ManagedImageResourceGroupName: fakeResourceGroup +ManagedImageName: fakeName +ManagedImageId: fakeID +ManagedImageLocation: fakeLocation +ManagedImageOSDiskSnapshotName: fakeOsDiskSnapshotName +ManagedImageDataDiskSnapshotPrefix: fakeDataDiskSnapshotPrefix ` result := artifact.String() diff --git a/builder/azure/arm/builder.go b/builder/azure/arm/builder.go index c7cf65292..1b5a87722 100644 --- a/builder/azure/arm/builder.go +++ b/builder/azure/arm/builder.go @@ -200,8 +200,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack b.config.SharedGalleryDestination.SigDestinationReplicationRegions = append(normalizedReplicationRegions, managedImageLocation) } b.stateBag.Put(constants.ArmManagedImageSharedGalleryReplicationRegions, b.config.SharedGalleryDestination.SigDestinationReplicationRegions) - // TODO: amrita remove this log line - ui.Say(fmt.Sprintf("Managed Image region to SIG replications regions %v", b.stateBag.Get(constants.ArmManagedImageSharedGalleryReplicationRegions))) } if b.config.OSType == constants.Target_Linux { @@ -304,7 +302,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack if b.config.isManagedImage() { managedImageID := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/images/%s", b.config.SubscriptionID, b.config.ManagedImageResourceGroupName, b.config.ManagedImageName) - return NewManagedImageArtifact(b.config.OSType, b.config.ManagedImageResourceGroupName, b.config.ManagedImageName, b.config.manageImageLocation, managedImageID, b.config.ManagedImageOSDiskSnapshotName, b.config.ManagedImageDataDiskSnapshotPrefix) + return NewManagedImageArtifact(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)) } else if template, ok := b.stateBag.GetOk(constants.ArmCaptureTemplate); ok { return NewArtifact( template.(*CaptureTemplate), diff --git a/builder/azure/arm/config.go b/builder/azure/arm/config.go index 2cc70f43f..af34754dc 100644 --- a/builder/azure/arm/config.go +++ b/builder/azure/arm/config.go @@ -634,7 +634,7 @@ func assertRequiredParametersSet(c *Config, errs *packer.MultiError) { } } - if c.SharedGalleryDestination.SigDestinationGalleryName != "" { + if c.ManagedImageName != "" && c.ManagedImageResourceGroupName != "" && c.SharedGalleryDestination.SigDestinationGalleryName != "" { if c.SharedGalleryDestination.SigDestinationResourceGroup == "" { errs = packer.MultiErrorAppend(errs, fmt.Errorf("A resource_group must be specified for shared_image_gallery_destination")) } diff --git a/builder/azure/arm/config_test.go b/builder/azure/arm/config_test.go index ef5c9fb93..a60903501 100644 --- a/builder/azure/arm/config_test.go +++ b/builder/azure/arm/config_test.go @@ -1679,7 +1679,7 @@ func TestConfigShouldRejectSharedImageGalleryWithVhdTarget(t *testing.T) { _, _, err := newConfig(config, getPackerConfiguration()) if err != nil { - t.Log("expected an error if Shared Image Gallery source is used with VHD target", err) + t.Log("expected an error if Shared Image Gallery source is used with VHD target", err) // TODO: remove this, this error is coming from check in line # 537 in config.go file! } } diff --git a/builder/azure/arm/step_publish_to_shared_image_gallery.go b/builder/azure/arm/step_publish_to_shared_image_gallery.go index cfd270761..347a9002c 100644 --- a/builder/azure/arm/step_publish_to_shared_image_gallery.go +++ b/builder/azure/arm/step_publish_to_shared_image_gallery.go @@ -11,7 +11,7 @@ import ( type StepPublishToSharedImageGallery struct { client *AzureClient - publish func(ctx context.Context, mdiID, miSigPubRg, miSIGalleryName, miSGImageName, miSGImageVersion string, miSigReplicationRegions []string, location string, tags map[string]*string) error + publish func(ctx context.Context, mdiID, miSigPubRg, miSIGalleryName, miSGImageName, miSGImageVersion string, miSigReplicationRegions []string, location string, tags map[string]*string) (string, error) say func(message string) error func(e error) toSIG func() bool @@ -35,7 +35,7 @@ func NewStepPublishToSharedImageGallery(client *AzureClient, ui packer.Ui, confi return step } -func (s *StepPublishToSharedImageGallery) publishToSig(ctx context.Context, mdiID string, miSigPubRg string, miSIGalleryName string, miSGImageName string, miSGImageVersion string, miSigReplicationRegions []string, location string, tags map[string]*string) error { +func (s *StepPublishToSharedImageGallery) publishToSig(ctx context.Context, mdiID string, miSigPubRg string, miSIGalleryName string, miSGImageName string, miSGImageVersion string, miSigReplicationRegions []string, location string, tags map[string]*string) (string, error) { replicationRegions := make([]compute.TargetRegion, len(miSigReplicationRegions)) for i, v := range miSigReplicationRegions { @@ -62,25 +62,25 @@ func (s *StepPublishToSharedImageGallery) publishToSig(ctx context.Context, mdiI if err != nil { s.say(s.client.LastError.Error()) - return err + return "", err } err = f.WaitForCompletionRef(ctx, s.client.GalleryImageVersionsClient.Client) if err != nil { s.say(s.client.LastError.Error()) - return err + return "", err } createdSGImageVersion, err := f.Result(s.client.GalleryImageVersionsClient) if err != nil { s.say(s.client.LastError.Error()) - return err + return "", err } s.say(fmt.Sprintf(" -> Shared Gallery Image Version ID : '%s'", *(createdSGImageVersion.ID))) - return nil + return *(createdSGImageVersion.ID), nil } func (s *StepPublishToSharedImageGallery) Run(ctx context.Context, stateBag multistep.StateBag) multistep.StepAction { @@ -108,7 +108,7 @@ func (s *StepPublishToSharedImageGallery) Run(ctx context.Context, stateBag mult s.say(fmt.Sprintf(" -> SIG image name : '%s'", miSGImageName)) s.say(fmt.Sprintf(" -> SIG image version : '%s'", miSGImageVersion)) s.say(fmt.Sprintf(" -> SIG replication regions : '%v'", miSigReplicationRegions)) - err := s.publish(ctx, mdiID, miSigPubRg, miSIGalleryName, miSGImageName, miSGImageVersion, miSigReplicationRegions, location, tags) + createdGalleryImageVersionID, err := s.publish(ctx, mdiID, miSigPubRg, miSIGalleryName, miSGImageName, miSGImageVersion, miSigReplicationRegions, location, tags) if err != nil { stateBag.Put(constants.Error, err) @@ -117,6 +117,7 @@ func (s *StepPublishToSharedImageGallery) Run(ctx context.Context, stateBag mult return multistep.ActionHalt } + stateBag.Put(constants.ArmManagedImageSharedGalleryId, createdGalleryImageVersionID) return multistep.ActionContinue } diff --git a/builder/azure/arm/step_publish_to_shared_image_gallery_test.go b/builder/azure/arm/step_publish_to_shared_image_gallery_test.go new file mode 100644 index 000000000..97c7aa289 --- /dev/null +++ b/builder/azure/arm/step_publish_to_shared_image_gallery_test.go @@ -0,0 +1,84 @@ +package arm + +import ( + "context" + "github.com/hashicorp/packer/builder/azure/common/constants" + "github.com/hashicorp/packer/helper/multistep" + "testing" +) + +func TestStepPublishToSharedImageGalleryShouldNotPublishForVhd(t *testing.T) { + var testSubject = &StepPublishToSharedImageGallery{ + publish: func(context.Context, string, string, string, string, string, []string, string, map[string]*string) (string, error) { + return "test", nil + }, + say: func(message string) {}, + error: func(e error) {}, + toSIG: func() bool { return false }, + } + + stateBag := createTestStateBagStepPublishToSharedImageGalleryForVhd() + var result = testSubject.Run(context.Background(), stateBag) + if result != multistep.ActionContinue { + t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result) + } + + if _, ok := stateBag.GetOk(constants.Error); ok == true { + t.Fatalf("Expected the step to not set stateBag['%s'], but it was.", constants.Error) + } +} + +func TestStepPublishToSharedImageGalleryShouldPublishForManagedImageWithSig(t *testing.T) { + var testSubject = &StepPublishToSharedImageGallery{ + publish: func(context.Context, string, string, string, string, string, []string, string, map[string]*string) (string, error) { + return "", nil + }, + say: func(message string) {}, + error: func(e error) {}, + toSIG: func() bool { return true }, + } + + stateBag := createTestStateBagStepPublishToSharedImageGallery() + var result = testSubject.Run(context.Background(), stateBag) + if result != multistep.ActionContinue { + t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result) + } + + if _, ok := stateBag.GetOk(constants.Error); ok == true { + t.Fatalf("Expected the step to not set stateBag['%s'], but it was.", constants.Error) + } +} + +func createTestStateBagStepPublishToSharedImageGallery() multistep.StateBag { + stateBag := new(multistep.BasicStateBag) + + stateBag.Put(constants.ArmManagedImageSigPublishResourceGroup, "Unit Test: ManagedImageSigPublishResourceGroup") + stateBag.Put(constants.ArmManagedImageSharedGalleryName, "Unit Test: ManagedImageSharedGalleryName") + stateBag.Put(constants.ArmManagedImageSharedGalleryImageName, "Unit Test: ManagedImageSharedGalleryImageName") + stateBag.Put(constants.ArmManagedImageSharedGalleryImageVersion, "Unit Test: ManagedImageSharedGalleryImageVersion") + stateBag.Put(constants.ArmLocation, "Unit Test: Location") + value := "Unit Test: Tags" + tags := map[string]*string{ + "tag01": &value, + } + stateBag.Put(constants.ArmTags, tags) + stateBag.Put(constants.ArmManagedImageSharedGalleryReplicationRegions, []string{"ManagedImageSharedGalleryReplicationRegionA", "ManagedImageSharedGalleryReplicationRegionB"}) + stateBag.Put(constants.ArmManagedImageResourceGroupName, "Unit Test: ManagedImageResourceGroupName") + stateBag.Put(constants.ArmManagedImageName, "Unit Test: ManagedImageName") + stateBag.Put(constants.ArmManagedImageSubscription, "Unit Test: ManagedImageSubscription") + + return stateBag +} + +func createTestStateBagStepPublishToSharedImageGalleryForVhd() multistep.StateBag { + stateBag := new(multistep.BasicStateBag) + + stateBag.Put(constants.ArmLocation, "Unit Test: Location") + value := "Unit Test: Tags" + tags := map[string]*string{ + "tag01": &value, + } + stateBag.Put(constants.ArmTags, tags) + + return stateBag +} diff --git a/builder/azure/common/constants/stateBag.go b/builder/azure/common/constants/stateBag.go index cd3c597f0..c68afd508 100644 --- a/builder/azure/common/constants/stateBag.go +++ b/builder/azure/common/constants/stateBag.go @@ -39,6 +39,7 @@ const ( ArmManagedImageSharedGalleryImageName string = "arm.ManagedImageSharedGalleryImageName" ArmManagedImageSharedGalleryImageVersion string = "arm.ManagedImageSharedGalleryImageVersion" ArmManagedImageSharedGalleryReplicationRegions string = "arm.ManagedImageSharedGalleryReplicationRegions" + ArmManagedImageSharedGalleryId string = "arm.ArmManagedImageSharedGalleryId" ArmManagedImageSubscription string = "arm.ArmManagedImageSubscription" ArmAsyncResourceGroupDelete string = "arm.AsyncResourceGroupDelete" ArmManagedImageOSDiskSnapshotName string = "arm.ManagedImageOSDiskSnapshotName"