Adds `force_delete_snapshot` flag
This PR adds the ability for Packer to clean up snapshots in addition to deregistering AMIs at build time. To test this, I used the following `test.json` file: ```json { "builders": [ { "type": "amazon-ebs", "region": "us-east-1", "source_ami": "ami-fce3c696", "ami_name": "packer-test", "instance_type": "m3.medium", "ssh_username": "ubuntu", "vpc_id": "some-vpc-id", "subnet_id": "some-subnet-routed-through-igw", "security_group_id": "some-security-group-with-port-22-access", "force_delete_snapshot": true } ], "provisioners": [ { "type": "shell-local", "command": "echo 'hello'" } ] } ``` I appreciate any constructive feedbakc that can be given. Cheers!
This commit is contained in:
parent
be4086f5fc
commit
5b59f56cdb
|
@ -244,8 +244,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
&StepEarlyCleanup{},
|
&StepEarlyCleanup{},
|
||||||
&StepSnapshot{},
|
&StepSnapshot{},
|
||||||
&awscommon.StepDeregisterAMI{
|
&awscommon.StepDeregisterAMI{
|
||||||
ForceDeregister: b.config.AMIForceDeregister,
|
ForceDeregister: b.config.AMIForceDeregister,
|
||||||
AMIName: b.config.AMIName,
|
ForceDeleteSnapshot: b.config.AMIForceDeleteSnapshot,
|
||||||
|
AMIName: b.config.AMIName,
|
||||||
},
|
},
|
||||||
&StepRegisterAMI{
|
&StepRegisterAMI{
|
||||||
RootVolumeSize: b.config.RootVolumeSize,
|
RootVolumeSize: b.config.RootVolumeSize,
|
||||||
|
|
|
@ -19,6 +19,7 @@ type AMIConfig struct {
|
||||||
AMITags map[string]string `mapstructure:"tags"`
|
AMITags map[string]string `mapstructure:"tags"`
|
||||||
AMIEnhancedNetworking bool `mapstructure:"enhanced_networking"`
|
AMIEnhancedNetworking bool `mapstructure:"enhanced_networking"`
|
||||||
AMIForceDeregister bool `mapstructure:"force_deregister"`
|
AMIForceDeregister bool `mapstructure:"force_deregister"`
|
||||||
|
AMIForceDeleteSnapshot bool `mapstructure:"force_delete_snapshot"`
|
||||||
AMIEncryptBootVolume bool `mapstructure:"encrypt_boot"`
|
AMIEncryptBootVolume bool `mapstructure:"encrypt_boot"`
|
||||||
SnapshotTags map[string]string `mapstructure:"snapshot_tags"`
|
SnapshotTags map[string]string `mapstructure:"snapshot_tags"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,15 +10,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepDeregisterAMI struct {
|
type StepDeregisterAMI struct {
|
||||||
ForceDeregister bool
|
ForceDeregister bool
|
||||||
AMIName string
|
ForceDeleteSnapshot bool
|
||||||
|
AMIName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StepDeregisterAMI) Run(state multistep.StateBag) multistep.StepAction {
|
func (s *StepDeregisterAMI) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
// check for force deregister
|
// Check for force deregister
|
||||||
if s.ForceDeregister {
|
if s.ForceDeregister {
|
||||||
resp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{
|
resp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{
|
||||||
Filters: []*ec2.Filter{{
|
Filters: []*ec2.Filter{{
|
||||||
|
@ -33,7 +34,7 @@ func (s *StepDeregisterAMI) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
// deregister image(s) by that name
|
// Deregister image(s) by name
|
||||||
for _, i := range resp.Images {
|
for _, i := range resp.Images {
|
||||||
_, err := ec2conn.DeregisterImage(&ec2.DeregisterImageInput{
|
_, err := ec2conn.DeregisterImage(&ec2.DeregisterImageInput{
|
||||||
ImageId: i.ImageId,
|
ImageId: i.ImageId,
|
||||||
|
@ -46,6 +47,25 @@ func (s *StepDeregisterAMI) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
ui.Say(fmt.Sprintf("Deregistered AMI %s, id: %s", s.AMIName, *i.ImageId))
|
ui.Say(fmt.Sprintf("Deregistered AMI %s, id: %s", s.AMIName, *i.ImageId))
|
||||||
|
|
||||||
|
// Delete snapshot(s) by image
|
||||||
|
if s.ForceDeleteSnapshot {
|
||||||
|
for _, b := range i.BlockDeviceMappings {
|
||||||
|
if b.Ebs != nil {
|
||||||
|
_, err := ec2conn.DeleteSnapshot(&ec2.DeleteSnapshotInput{
|
||||||
|
SnapshotId: b.Ebs.SnapshotId,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Error deleting existing snapshot: %s", err)
|
||||||
|
state.Put("error", err)
|
||||||
|
ui.Error(err.Error())
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
ui.Say(fmt.Sprintf("Deleted snapshot: %s", *b.Ebs.SnapshotId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,8 +165,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
EnableEnhancedNetworking: b.config.AMIEnhancedNetworking,
|
EnableEnhancedNetworking: b.config.AMIEnhancedNetworking,
|
||||||
},
|
},
|
||||||
&awscommon.StepDeregisterAMI{
|
&awscommon.StepDeregisterAMI{
|
||||||
ForceDeregister: b.config.AMIForceDeregister,
|
ForceDeregister: b.config.AMIForceDeregister,
|
||||||
AMIName: b.config.AMIName,
|
ForceDeleteSnapshot: b.config.AMIForceDeleteSnapshot,
|
||||||
|
AMIName: b.config.AMIName,
|
||||||
},
|
},
|
||||||
&stepCreateAMI{},
|
&stepCreateAMI{},
|
||||||
&stepCreateEncryptedAMICopy{},
|
&stepCreateEncryptedAMICopy{},
|
||||||
|
|
|
@ -46,6 +46,22 @@ func TestBuilderAcc_forceDeregister(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuilderAcc_forceDeleteSnapshot(t *testing.T) {
|
||||||
|
// Build the same AMI name twice, with force_delete_snapshot on the second run
|
||||||
|
builderT.Test(t, builderT.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Builder: &Builder{},
|
||||||
|
Template: buildForceDeleteSnapshotConfig("false", "dereg"),
|
||||||
|
SkipArtifactTeardown: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
builderT.Test(t, builderT.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Builder: &Builder{},
|
||||||
|
Template: buildForceDeleteSnapshotConfig("true", "dereg"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuilderAcc_amiSharing(t *testing.T) {
|
func TestBuilderAcc_amiSharing(t *testing.T) {
|
||||||
builderT.Test(t, builderT.TestCase{
|
builderT.Test(t, builderT.TestCase{
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
@ -254,6 +270,21 @@ const testBuilderAccForceDeregister = `
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const testBuilderAccForceDeleteSnapshot = `
|
||||||
|
{
|
||||||
|
"builders": [{
|
||||||
|
"type": "test",
|
||||||
|
"region": "us-east-1",
|
||||||
|
"instance_type": "m3.medium",
|
||||||
|
"source_ami": "ami-76b2a71e",
|
||||||
|
"ssh_username": "ubuntu",
|
||||||
|
"force_deregister": "%s",
|
||||||
|
"force_delete_snapshot": "%s",
|
||||||
|
"ami_name": "packer-test-%s"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
// share with catsby
|
// share with catsby
|
||||||
const testBuilderAccSharing = `
|
const testBuilderAccSharing = `
|
||||||
{
|
{
|
||||||
|
@ -284,6 +315,10 @@ const testBuilderAccEncrypted = `
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
func buildForceDeregisterConfig(name, flag string) string {
|
func buildForceDeregisterConfig(val, name string) string {
|
||||||
return fmt.Sprintf(testBuilderAccForceDeregister, name, flag)
|
return fmt.Sprintf(testBuilderAccForceDeregister, val, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildForceDeleteSnapshotConfig(val, name string) string {
|
||||||
|
return fmt.Sprintf(testBuilderAccForceDeleteSnapshot, val, val, name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,8 +247,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
Debug: b.config.PackerDebug,
|
Debug: b.config.PackerDebug,
|
||||||
},
|
},
|
||||||
&awscommon.StepDeregisterAMI{
|
&awscommon.StepDeregisterAMI{
|
||||||
ForceDeregister: b.config.AMIForceDeregister,
|
ForceDeregister: b.config.AMIForceDeregister,
|
||||||
AMIName: b.config.AMIName,
|
ForceDeleteSnapshot: b.config.AMIForceDeleteSnapshot,
|
||||||
|
AMIName: b.config.AMIName,
|
||||||
},
|
},
|
||||||
&StepRegisterAMI{},
|
&StepRegisterAMI{},
|
||||||
&awscommon.StepAMIRegionCopy{
|
&awscommon.StepAMIRegionCopy{
|
||||||
|
|
|
@ -124,6 +124,9 @@ each category, the available configuration keys are alphabetized.
|
||||||
- `force_deregister` (boolean) - Force Packer to first deregister an existing
|
- `force_deregister` (boolean) - Force Packer to first deregister an existing
|
||||||
AMI if one with the same name already exists. Default `false`.
|
AMI if one with the same name already exists. Default `false`.
|
||||||
|
|
||||||
|
- `force_delete_snapshot` (boolean) - Force Packer to delete snapshots associated with
|
||||||
|
AMIs, which have been deregistered by `force_deregister`. Default `false`.
|
||||||
|
|
||||||
- `from_scratch` (boolean) - Build a new volume instead of starting from an
|
- `from_scratch` (boolean) - Build a new volume instead of starting from an
|
||||||
existing AMI root volume snapshot. Default `false`. If true, `source_ami` is
|
existing AMI root volume snapshot. Default `false`. If true, `source_ami` is
|
||||||
no longer used and the following options become required:
|
no longer used and the following options become required:
|
||||||
|
|
|
@ -155,6 +155,9 @@ builder.
|
||||||
- `force_deregister` (boolean) - Force Packer to first deregister an existing
|
- `force_deregister` (boolean) - Force Packer to first deregister an existing
|
||||||
AMI if one with the same name already exists. Default `false`.
|
AMI if one with the same name already exists. Default `false`.
|
||||||
|
|
||||||
|
- `force_delete_snapshot` (boolean) - Force Packer to delete snapshots associated with
|
||||||
|
AMIs, which have been deregistered by `force_deregister`. Default `false`.
|
||||||
|
|
||||||
- `encrypt_boot` (boolean) - Instruct packer to automatically create a copy of the
|
- `encrypt_boot` (boolean) - Instruct packer to automatically create a copy of the
|
||||||
AMI with an encrypted boot volume (discarding the initial unencrypted AMI in the
|
AMI with an encrypted boot volume (discarding the initial unencrypted AMI in the
|
||||||
process). Default `false`.
|
process). Default `false`.
|
||||||
|
|
|
@ -179,6 +179,9 @@ builder.
|
||||||
- `force_deregister` (boolean) - Force Packer to first deregister an existing
|
- `force_deregister` (boolean) - Force Packer to first deregister an existing
|
||||||
AMI if one with the same name already exists. Default `false`.
|
AMI if one with the same name already exists. Default `false`.
|
||||||
|
|
||||||
|
- `force_delete_snapshot` (boolean) - Force Packer to delete snapshots associated with
|
||||||
|
AMIs, which have been deregistered by `force_deregister`. Default `false`.
|
||||||
|
|
||||||
- `iam_instance_profile` (string) - The name of an [IAM instance
|
- `iam_instance_profile` (string) - The name of an [IAM instance
|
||||||
profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html)
|
profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html)
|
||||||
to launch the EC2 instance with.
|
to launch the EC2 instance with.
|
||||||
|
|
Loading…
Reference in New Issue