github.phpd.cn/hashicorp/packer@v1.3.2/builder/amazon/common/block_device.go (about)

     1  package common
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/aws/aws-sdk-go/aws"
     8  	"github.com/aws/aws-sdk-go/service/ec2"
     9  	"github.com/hashicorp/packer/template/interpolate"
    10  )
    11  
    12  // BlockDevice
    13  type BlockDevice struct {
    14  	DeleteOnTermination bool   `mapstructure:"delete_on_termination"`
    15  	DeviceName          string `mapstructure:"device_name"`
    16  	Encrypted           bool   `mapstructure:"encrypted"`
    17  	IOPS                int64  `mapstructure:"iops"`
    18  	NoDevice            bool   `mapstructure:"no_device"`
    19  	SnapshotId          string `mapstructure:"snapshot_id"`
    20  	VirtualName         string `mapstructure:"virtual_name"`
    21  	VolumeType          string `mapstructure:"volume_type"`
    22  	VolumeSize          int64  `mapstructure:"volume_size"`
    23  	KmsKeyId            string `mapstructure:"kms_key_id"`
    24  }
    25  
    26  type BlockDevices struct {
    27  	AMIBlockDevices    `mapstructure:",squash"`
    28  	LaunchBlockDevices `mapstructure:",squash"`
    29  }
    30  
    31  type AMIBlockDevices struct {
    32  	AMIMappings []BlockDevice `mapstructure:"ami_block_device_mappings"`
    33  }
    34  
    35  type LaunchBlockDevices struct {
    36  	LaunchMappings []BlockDevice `mapstructure:"launch_block_device_mappings"`
    37  }
    38  
    39  func buildBlockDevices(b []BlockDevice) []*ec2.BlockDeviceMapping {
    40  	var blockDevices []*ec2.BlockDeviceMapping
    41  
    42  	for _, blockDevice := range b {
    43  		mapping := &ec2.BlockDeviceMapping{
    44  			DeviceName: aws.String(blockDevice.DeviceName),
    45  		}
    46  
    47  		if blockDevice.NoDevice {
    48  			mapping.NoDevice = aws.String("")
    49  		} else if blockDevice.VirtualName != "" {
    50  			if strings.HasPrefix(blockDevice.VirtualName, "ephemeral") {
    51  				mapping.VirtualName = aws.String(blockDevice.VirtualName)
    52  			}
    53  		} else {
    54  			ebsBlockDevice := &ec2.EbsBlockDevice{
    55  				DeleteOnTermination: aws.Bool(blockDevice.DeleteOnTermination),
    56  			}
    57  
    58  			if blockDevice.VolumeType != "" {
    59  				ebsBlockDevice.VolumeType = aws.String(blockDevice.VolumeType)
    60  			}
    61  
    62  			if blockDevice.VolumeSize > 0 {
    63  				ebsBlockDevice.VolumeSize = aws.Int64(blockDevice.VolumeSize)
    64  			}
    65  
    66  			// IOPS is only valid for io1 type
    67  			if blockDevice.VolumeType == "io1" {
    68  				ebsBlockDevice.Iops = aws.Int64(blockDevice.IOPS)
    69  			}
    70  
    71  			// You cannot specify Encrypted if you specify a Snapshot ID
    72  			if blockDevice.SnapshotId != "" {
    73  				ebsBlockDevice.SnapshotId = aws.String(blockDevice.SnapshotId)
    74  			} else if blockDevice.Encrypted {
    75  				ebsBlockDevice.Encrypted = aws.Bool(blockDevice.Encrypted)
    76  			}
    77  
    78  			if blockDevice.KmsKeyId != "" {
    79  				ebsBlockDevice.KmsKeyId = aws.String(blockDevice.KmsKeyId)
    80  			}
    81  
    82  			mapping.Ebs = ebsBlockDevice
    83  		}
    84  
    85  		blockDevices = append(blockDevices, mapping)
    86  	}
    87  	return blockDevices
    88  }
    89  
    90  func (b *BlockDevice) Prepare(ctx *interpolate.Context) error {
    91  	if b.DeviceName == "" {
    92  		return fmt.Errorf("The `device_name` must be specified " +
    93  			"for every device in the block device mapping.")
    94  	}
    95  	// Warn that encrypted must be true when setting kms_key_id
    96  	if b.KmsKeyId != "" && b.Encrypted == false {
    97  		return fmt.Errorf("The device %v, must also have `encrypted: "+
    98  			"true` when setting a kms_key_id.", b.DeviceName)
    99  	}
   100  	return nil
   101  }
   102  
   103  func (b *BlockDevices) Prepare(ctx *interpolate.Context) (errs []error) {
   104  	for _, d := range b.AMIMappings {
   105  		if err := d.Prepare(ctx); err != nil {
   106  			errs = append(errs, fmt.Errorf("AMIMapping: %s", err.Error()))
   107  		}
   108  	}
   109  	for _, d := range b.LaunchMappings {
   110  		if err := d.Prepare(ctx); err != nil {
   111  			errs = append(errs, fmt.Errorf("LaunchMapping: %s", err.Error()))
   112  		}
   113  	}
   114  	return errs
   115  }
   116  
   117  func (b *AMIBlockDevices) BuildAMIDevices() []*ec2.BlockDeviceMapping {
   118  	return buildBlockDevices(b.AMIMappings)
   119  }
   120  
   121  func (b *LaunchBlockDevices) BuildLaunchDevices() []*ec2.BlockDeviceMapping {
   122  	return buildBlockDevices(b.LaunchMappings)
   123  }