From 9b724d4ca05e7f151929375ef1a9d47777ef47f4 Mon Sep 17 00:00:00 2001 From: Paul Meyer Date: Mon, 7 Oct 2019 19:20:08 +0000 Subject: [PATCH] Add artifact --- builder/azure/chroot/builder.go | 11 +++- builder/azure/common/artifact.go | 103 +++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 builder/azure/common/artifact.go diff --git a/builder/azure/chroot/builder.go b/builder/azure/chroot/builder.go index a5e26f9b3..27f763706 100644 --- a/builder/azure/chroot/builder.go +++ b/builder/azure/chroot/builder.go @@ -28,6 +28,9 @@ import ( "github.com/Azure/go-autorest/autorest/to" ) +// BuilderId is the unique ID for this builder +const BuilderId = "azure.chroot" + // Config is the configuration that is chained through the steps and settable // from the template. type Config struct { @@ -437,7 +440,13 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack return nil, rawErr.(error) } - return nil, nil + // Build the artifact and return it + artifact := &azcommon.Artifact{ + Resources: []string{b.config.ImageResourceID}, + BuilderIdValue: BuilderId, + } + + return artifact, nil } var _ packer.Builder = &Builder{} diff --git a/builder/azure/common/artifact.go b/builder/azure/common/artifact.go new file mode 100644 index 000000000..d74ff9b54 --- /dev/null +++ b/builder/azure/common/artifact.go @@ -0,0 +1,103 @@ +package common + +import ( + "context" + "fmt" + "log" + "sort" + "strings" + + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/packer/builder/azure/common/client" + "github.com/hashicorp/packer/packer" +) + +// Artifact is an artifact implementation that contains built Managed Images or Disks. +type Artifact struct { + // Array of the Azure resource IDs that were created. + Resources []string + + // BuilderId is the unique ID for the builder that created this AMI + BuilderIdValue string + + // Azure client for performing API stuff. + AzureClientSet client.AzureClientSet +} + +func (a *Artifact) BuilderId() string { + return a.BuilderIdValue +} + +func (*Artifact) Files() []string { + // We have no files + return nil +} + +func (a *Artifact) Id() string { + parts := make([]string, 0, len(a.Resources)) + for _, resource := range a.Resources { + parts = append(parts, strings.ToLower(resource)) + } + + sort.Strings(parts) + return strings.Join(parts, ",") +} + +func (a *Artifact) String() string { + parts := make([]string, 0, len(a.Resources)) + for _, resource := range a.Resources { + parts = append(parts, strings.ToLower(resource)) + } + + sort.Strings(parts) + return fmt.Sprintf("Azure resources created:\n%s\n", strings.Join(parts, "\n")) +} + +func (a *Artifact) State(name string) interface{} { + switch name { + default: + return nil + } +} + +func (a *Artifact) Destroy() error { + errs := make([]error, 0) + + for _, resource := range a.Resources { + log.Printf("Deleting resource %s", resource) + + id, err := azure.ParseResourceID(resource) + if err != nil { + return fmt.Errorf("Unable to parse resource id (%s): %v", resource, err) + } + + ctx := context.TODO() + restype := strings.ToLower(fmt.Sprintf("%s/%s", id.Provider, id.ResourceType)) + + switch restype { + case "microsoft.compute/images": + res, err := a.AzureClientSet.ImagesClient().Delete(ctx, id.ResourceGroup, id.ResourceName) + if err != nil { + errs = append(errs, fmt.Errorf("Unable to initiate deletion of resource (%s): %v", resource, err)) + } else { + err := res.WaitForCompletionRef(ctx, a.AzureClientSet.PollClient()) + if err != nil { + errs = append(errs, fmt.Errorf("Unable to complete deletion of resource (%s): %v", resource, err)) + } + } + default: + errs = append(errs, fmt.Errorf("Don't know how to delete resources of type %s (%s)", resource, restype)) + } + + } + + if len(errs) > 0 { + if len(errs) == 1 { + return errs[0] + } else { + return &packer.MultiError{Errors: errs} + } + } + + return nil +}