Enable setting the volume type when building with the Amazon Chroot builder
This commit is contained in:
parent
b94e6e913e
commit
07ce820c70
|
@ -42,6 +42,7 @@ type Config struct {
|
||||||
PreMountCommands []string `mapstructure:"pre_mount_commands"`
|
PreMountCommands []string `mapstructure:"pre_mount_commands"`
|
||||||
RootDeviceName string `mapstructure:"root_device_name"`
|
RootDeviceName string `mapstructure:"root_device_name"`
|
||||||
RootVolumeSize int64 `mapstructure:"root_volume_size"`
|
RootVolumeSize int64 `mapstructure:"root_volume_size"`
|
||||||
|
RootVolumeType string `mapstructure:"root_volume_type"`
|
||||||
SourceAmi string `mapstructure:"source_ami"`
|
SourceAmi string `mapstructure:"source_ami"`
|
||||||
SourceAmiFilter awscommon.AmiFilterOptions `mapstructure:"source_ami_filter"`
|
SourceAmiFilter awscommon.AmiFilterOptions `mapstructure:"source_ami_filter"`
|
||||||
RootVolumeTags awscommon.TagMap `mapstructure:"root_volume_tags"`
|
RootVolumeTags awscommon.TagMap `mapstructure:"root_volume_tags"`
|
||||||
|
@ -233,6 +234,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
&StepFlock{},
|
&StepFlock{},
|
||||||
&StepPrepareDevice{},
|
&StepPrepareDevice{},
|
||||||
&StepCreateVolume{
|
&StepCreateVolume{
|
||||||
|
RootVolumeType: b.config.RootVolumeType,
|
||||||
RootVolumeSize: b.config.RootVolumeSize,
|
RootVolumeSize: b.config.RootVolumeSize,
|
||||||
RootVolumeTags: b.config.RootVolumeTags,
|
RootVolumeTags: b.config.RootVolumeTags,
|
||||||
Ctx: b.config.ctx,
|
Ctx: b.config.ctx,
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
type StepCreateVolume struct {
|
type StepCreateVolume struct {
|
||||||
volumeId string
|
volumeId string
|
||||||
RootVolumeSize int64
|
RootVolumeSize int64
|
||||||
|
RootVolumeType string
|
||||||
RootVolumeTags awscommon.TagMap
|
RootVolumeTags awscommon.TagMap
|
||||||
Ctx interpolate.Context
|
Ctx interpolate.Context
|
||||||
}
|
}
|
||||||
|
@ -70,26 +71,13 @@ func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) mu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if rootDevice == nil {
|
ui.Say("Creating the root volume...")
|
||||||
err := fmt.Errorf("Couldn't find root device!")
|
createVolume, err = s.buildCreateVolumeInput(*instance.Placement.AvailabilityZone, rootDevice)
|
||||||
|
if err != nil {
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say("Creating the root volume...")
|
|
||||||
vs := *rootDevice.Ebs.VolumeSize
|
|
||||||
if s.RootVolumeSize > *rootDevice.Ebs.VolumeSize {
|
|
||||||
vs = s.RootVolumeSize
|
|
||||||
}
|
|
||||||
|
|
||||||
createVolume = &ec2.CreateVolumeInput{
|
|
||||||
AvailabilityZone: instance.Placement.AvailabilityZone,
|
|
||||||
Size: aws.Int64(vs),
|
|
||||||
SnapshotId: rootDevice.Ebs.SnapshotId,
|
|
||||||
VolumeType: rootDevice.Ebs.VolumeType,
|
|
||||||
Iops: rootDevice.Ebs.Iops,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(tagSpecs) > 0 {
|
if len(tagSpecs) > 0 {
|
||||||
|
@ -137,3 +125,33 @@ func (s *StepCreateVolume) Cleanup(state multistep.StateBag) {
|
||||||
ui.Error(fmt.Sprintf("Error deleting EBS volume: %s", err))
|
ui.Error(fmt.Sprintf("Error deleting EBS volume: %s", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *StepCreateVolume) buildCreateVolumeInput(az string, rootDevice *ec2.BlockDeviceMapping) (*ec2.CreateVolumeInput, error) {
|
||||||
|
if rootDevice == nil {
|
||||||
|
return nil, fmt.Errorf("Couldn't find root device!")
|
||||||
|
}
|
||||||
|
createVolumeInput := &ec2.CreateVolumeInput{
|
||||||
|
AvailabilityZone: aws.String(az),
|
||||||
|
Size: rootDevice.Ebs.VolumeSize,
|
||||||
|
SnapshotId: rootDevice.Ebs.SnapshotId,
|
||||||
|
VolumeType: rootDevice.Ebs.VolumeType,
|
||||||
|
Iops: rootDevice.Ebs.Iops,
|
||||||
|
}
|
||||||
|
if s.RootVolumeSize > *rootDevice.Ebs.VolumeSize {
|
||||||
|
createVolumeInput.Size = aws.Int64(s.RootVolumeSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.RootVolumeType == "" || s.RootVolumeType == *rootDevice.Ebs.VolumeType {
|
||||||
|
return createVolumeInput, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.RootVolumeType == "io1" {
|
||||||
|
return nil, fmt.Errorf("Root volume type cannot be io1, because existing root volume type was %s", *rootDevice.Ebs.VolumeType)
|
||||||
|
}
|
||||||
|
|
||||||
|
createVolumeInput.VolumeType = aws.String(s.RootVolumeType)
|
||||||
|
// non io1 cannot set iops
|
||||||
|
createVolumeInput.Iops = nil
|
||||||
|
|
||||||
|
return createVolumeInput, nil
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package chroot
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func buildTestRootDevice() *ec2.BlockDeviceMapping {
|
||||||
|
return &ec2.BlockDeviceMapping{
|
||||||
|
Ebs: &ec2.EbsBlockDevice{
|
||||||
|
VolumeSize: aws.Int64(10),
|
||||||
|
SnapshotId: aws.String("snap-1234"),
|
||||||
|
VolumeType: aws.String("gp2"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateVolume_Default(t *testing.T) {
|
||||||
|
stepCreateVolume := new(StepCreateVolume)
|
||||||
|
_, err := stepCreateVolume.buildCreateVolumeInput("test-az", buildTestRootDevice())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateVolume_Shrink(t *testing.T) {
|
||||||
|
stepCreateVolume := StepCreateVolume{RootVolumeSize: 1}
|
||||||
|
testRootDevice := buildTestRootDevice()
|
||||||
|
ret, err := stepCreateVolume.buildCreateVolumeInput("test-az", testRootDevice)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// Ensure that the new value is equal to the size of the old root device
|
||||||
|
assert.Equal(t, *ret.Size, *testRootDevice.Ebs.VolumeSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateVolume_Expand(t *testing.T) {
|
||||||
|
stepCreateVolume := StepCreateVolume{RootVolumeSize: 25}
|
||||||
|
testRootDevice := buildTestRootDevice()
|
||||||
|
ret, err := stepCreateVolume.buildCreateVolumeInput("test-az", testRootDevice)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// Ensure that the new value is equal to the size of the value passed in
|
||||||
|
assert.Equal(t, *ret.Size, stepCreateVolume.RootVolumeSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateVolume_io1_to_io1(t *testing.T) {
|
||||||
|
stepCreateVolume := StepCreateVolume{RootVolumeType: "io1"}
|
||||||
|
testRootDevice := buildTestRootDevice()
|
||||||
|
testRootDevice.Ebs.VolumeType = aws.String("io1")
|
||||||
|
testRootDevice.Ebs.Iops = aws.Int64(1000)
|
||||||
|
ret, err := stepCreateVolume.buildCreateVolumeInput("test-az", testRootDevice)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, *ret.VolumeType, stepCreateVolume.RootVolumeType)
|
||||||
|
assert.Equal(t, *ret.Iops, *testRootDevice.Ebs.Iops)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateVolume_io1_to_gp2(t *testing.T) {
|
||||||
|
stepCreateVolume := StepCreateVolume{RootVolumeType: "gp2"}
|
||||||
|
testRootDevice := buildTestRootDevice()
|
||||||
|
testRootDevice.Ebs.VolumeType = aws.String("io1")
|
||||||
|
testRootDevice.Ebs.Iops = aws.Int64(1000)
|
||||||
|
|
||||||
|
ret, err := stepCreateVolume.buildCreateVolumeInput("test-az", testRootDevice)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, *ret.VolumeType, stepCreateVolume.RootVolumeType)
|
||||||
|
assert.Nil(t, ret.Iops)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateVolume_gp2_to_io1(t *testing.T) {
|
||||||
|
stepCreateVolume := StepCreateVolume{RootVolumeType: "io1"}
|
||||||
|
testRootDevice := buildTestRootDevice()
|
||||||
|
|
||||||
|
_, err := stepCreateVolume.buildCreateVolumeInput("test-az", testRootDevice)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
Loading…
Reference in New Issue