github.phpd.cn/hashicorp/packer@v1.3.2/builder/alicloud/ecs/artifact.go (about)

     1  package ecs
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"sort"
     7  	"strings"
     8  
     9  	"github.com/denverdino/aliyungo/common"
    10  	"github.com/denverdino/aliyungo/ecs"
    11  	"github.com/hashicorp/packer/packer"
    12  )
    13  
    14  type Artifact struct {
    15  	// A map of regions to alicloud image IDs.
    16  	AlicloudImages map[string]string
    17  
    18  	// BuilderId is the unique ID for the builder that created this alicloud image
    19  	BuilderIdValue string
    20  
    21  	// Alcloud connection for performing API stuff.
    22  	Client *ecs.Client
    23  }
    24  
    25  func (a *Artifact) BuilderId() string {
    26  	return a.BuilderIdValue
    27  }
    28  
    29  func (*Artifact) Files() []string {
    30  	// We have no files
    31  	return nil
    32  }
    33  
    34  func (a *Artifact) Id() string {
    35  	parts := make([]string, 0, len(a.AlicloudImages))
    36  	for region, ecsImageId := range a.AlicloudImages {
    37  		parts = append(parts, fmt.Sprintf("%s:%s", region, ecsImageId))
    38  	}
    39  
    40  	sort.Strings(parts)
    41  	return strings.Join(parts, ",")
    42  }
    43  
    44  func (a *Artifact) String() string {
    45  	alicloudImageStrings := make([]string, 0, len(a.AlicloudImages))
    46  	for region, id := range a.AlicloudImages {
    47  		single := fmt.Sprintf("%s: %s", region, id)
    48  		alicloudImageStrings = append(alicloudImageStrings, single)
    49  	}
    50  
    51  	sort.Strings(alicloudImageStrings)
    52  	return fmt.Sprintf("Alicloud images were created:\n\n%s", strings.Join(alicloudImageStrings, "\n"))
    53  }
    54  
    55  func (a *Artifact) State(name string) interface{} {
    56  	switch name {
    57  	case "atlas.artifact.metadata":
    58  		return a.stateAtlasMetadata()
    59  	default:
    60  		return nil
    61  	}
    62  }
    63  
    64  func (a *Artifact) Destroy() error {
    65  	errors := make([]error, 0)
    66  
    67  	for region, imageId := range a.AlicloudImages {
    68  		log.Printf("Delete alicloud image ID (%s) from region (%s)", imageId, region)
    69  
    70  		// Get alicloud image metadata
    71  		images, _, err := a.Client.DescribeImages(&ecs.DescribeImagesArgs{
    72  			RegionId: common.Region(region),
    73  			ImageId:  imageId})
    74  		if err != nil {
    75  			errors = append(errors, err)
    76  		}
    77  		if len(images) == 0 {
    78  			err := fmt.Errorf("Error retrieving details for alicloud image(%s), no alicloud images found", imageId)
    79  			errors = append(errors, err)
    80  			continue
    81  		}
    82  		//Unshared the shared account before destroy
    83  		sharePermissions, err := a.Client.DescribeImageSharePermission(&ecs.ModifyImageSharePermissionArgs{RegionId: common.Region(region), ImageId: imageId})
    84  		if err != nil {
    85  			errors = append(errors, err)
    86  		}
    87  		accountsNumber := len(sharePermissions.Accounts.Account)
    88  		if accountsNumber > 0 {
    89  			accounts := make([]string, accountsNumber)
    90  			for index, account := range sharePermissions.Accounts.Account {
    91  				accounts[index] = account.AliyunId
    92  			}
    93  			err := a.Client.ModifyImageSharePermission(&ecs.ModifyImageSharePermissionArgs{
    94  
    95  				RegionId:      common.Region(region),
    96  				ImageId:       imageId,
    97  				RemoveAccount: accounts,
    98  			})
    99  			if err != nil {
   100  				errors = append(errors, err)
   101  			}
   102  		}
   103  		// Delete alicloud images
   104  		if err := a.Client.DeleteImage(common.Region(region), imageId); err != nil {
   105  			errors = append(errors, err)
   106  		}
   107  		//Delete the snapshot of this images
   108  		for _, diskDevices := range images[0].DiskDeviceMappings.DiskDeviceMapping {
   109  			if err := a.Client.DeleteSnapshot(diskDevices.SnapshotId); err != nil {
   110  				errors = append(errors, err)
   111  			}
   112  		}
   113  
   114  	}
   115  
   116  	if len(errors) > 0 {
   117  		if len(errors) == 1 {
   118  			return errors[0]
   119  		} else {
   120  			return &packer.MultiError{Errors: errors}
   121  		}
   122  	}
   123  
   124  	return nil
   125  }
   126  
   127  func (a *Artifact) stateAtlasMetadata() interface{} {
   128  	metadata := make(map[string]string)
   129  	for region, imageId := range a.AlicloudImages {
   130  		k := fmt.Sprintf("region.%s", region)
   131  		metadata[k] = imageId
   132  	}
   133  
   134  	return metadata
   135  }