refactor aws test tooling so we can apply common test function helpers to ebsvolume tests

This commit is contained in:
Megan Marsh 2021-02-23 09:23:35 -08:00
parent aef74cd059
commit 160be7e773
7 changed files with 84 additions and 46 deletions

View File

@ -5,20 +5,10 @@ import (
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
) )
func testAccessConfig() *AccessConfig {
return &AccessConfig{
getEC2Connection: func() ec2iface.EC2API {
return &mockEC2Client{}
},
PollingConfig: new(AWSPollingConfig),
}
}
func TestAccessConfigPrepare_Region(t *testing.T) { func TestAccessConfigPrepare_Region(t *testing.T) {
c := testAccessConfig() c := FakeAccessConfig()
c.RawRegion = "us-east-12" c.RawRegion = "us-east-12"
err := c.ValidateRegion(c.RawRegion) err := c.ValidateRegion(c.RawRegion)
@ -40,7 +30,7 @@ func TestAccessConfigPrepare_Region(t *testing.T) {
} }
func TestAccessConfigPrepare_RegionRestricted(t *testing.T) { func TestAccessConfigPrepare_RegionRestricted(t *testing.T) {
c := testAccessConfig() c := FakeAccessConfig()
// Create a Session with a custom region // Create a Session with a custom region
c.session = session.Must(session.NewSession(&aws.Config{ c.session = session.Must(session.NewSession(&aws.Config{

View File

@ -7,7 +7,6 @@ import (
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/hashicorp/packer-plugin-sdk/template/config" "github.com/hashicorp/packer-plugin-sdk/template/config"
) )
@ -18,14 +17,14 @@ func testAMIConfig() *AMIConfig {
} }
func getFakeAccessConfig(region string) *AccessConfig { func getFakeAccessConfig(region string) *AccessConfig {
c := testAccessConfig() c := FakeAccessConfig()
c.RawRegion = region c.RawRegion = region
return c return c
} }
func TestAMIConfigPrepare_name(t *testing.T) { func TestAMIConfigPrepare_name(t *testing.T) {
c := testAMIConfig() c := testAMIConfig()
accessConf := testAccessConfig() accessConf := FakeAccessConfig()
if err := c.Prepare(accessConf, nil); err != nil { if err := c.Prepare(accessConf, nil); err != nil {
t.Fatalf("shouldn't have err: %s", err) t.Fatalf("shouldn't have err: %s", err)
} }
@ -36,10 +35,6 @@ func TestAMIConfigPrepare_name(t *testing.T) {
} }
} }
type mockEC2Client struct {
ec2iface.EC2API
}
func (m *mockEC2Client) DescribeRegions(*ec2.DescribeRegionsInput) (*ec2.DescribeRegionsOutput, error) { func (m *mockEC2Client) DescribeRegions(*ec2.DescribeRegionsInput) (*ec2.DescribeRegionsOutput, error) {
return &ec2.DescribeRegionsOutput{ return &ec2.DescribeRegionsOutput{
Regions: []*ec2.Region{ Regions: []*ec2.Region{
@ -56,7 +51,7 @@ func TestAMIConfigPrepare_regions(t *testing.T) {
var errs []error var errs []error
var err error var err error
accessConf := testAccessConfig() accessConf := FakeAccessConfig()
mockConn := &mockEC2Client{} mockConn := &mockEC2Client{}
if errs = c.prepareRegions(accessConf); len(errs) > 0 { if errs = c.prepareRegions(accessConf); len(errs) > 0 {
t.Fatalf("shouldn't have err: %#v", errs) t.Fatalf("shouldn't have err: %#v", errs)
@ -163,7 +158,7 @@ func TestAMIConfigPrepare_Share_EncryptedBoot(t *testing.T) {
c.AMIUsers = []string{"testAccountID"} c.AMIUsers = []string{"testAccountID"}
c.AMIEncryptBootVolume = config.TriTrue c.AMIEncryptBootVolume = config.TriTrue
accessConf := testAccessConfig() accessConf := FakeAccessConfig()
c.AMIKmsKeyId = "" c.AMIKmsKeyId = ""
if err := c.Prepare(accessConf, nil); err == nil { if err := c.Prepare(accessConf, nil); err == nil {
@ -179,7 +174,7 @@ func TestAMIConfigPrepare_ValidateKmsKey(t *testing.T) {
c := testAMIConfig() c := testAMIConfig()
c.AMIEncryptBootVolume = config.TriTrue c.AMIEncryptBootVolume = config.TriTrue
accessConf := testAccessConfig() accessConf := FakeAccessConfig()
validCases := []string{ validCases := []string{
"abcd1234-e567-890f-a12b-a123b4cd56ef", "abcd1234-e567-890f-a12b-a123b4cd56ef",
@ -215,7 +210,7 @@ func TestAMIConfigPrepare_ValidateKmsKey(t *testing.T) {
func TestAMINameValidation(t *testing.T) { func TestAMINameValidation(t *testing.T) {
c := testAMIConfig() c := testAMIConfig()
accessConf := testAccessConfig() accessConf := FakeAccessConfig()
c.AMIName = "aa" c.AMIName = "aa"
if err := c.Prepare(accessConf, nil); err == nil { if err := c.Prepare(accessConf, nil); err == nil {

View File

@ -105,7 +105,7 @@ func TestStepAMIRegionCopy_duplicates(t *testing.T) {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
stepAMIRegionCopy := StepAMIRegionCopy{ stepAMIRegionCopy := StepAMIRegionCopy{
AccessConfig: testAccessConfig(), AccessConfig: FakeAccessConfig(),
Regions: []string{"us-east-1"}, Regions: []string{"us-east-1"},
AMIKmsKeyId: "12345", AMIKmsKeyId: "12345",
// Original region key in regionkeyids is different than in amikmskeyid // Original region key in regionkeyids is different than in amikmskeyid
@ -131,7 +131,7 @@ func TestStepAMIRegionCopy_duplicates(t *testing.T) {
// the ami is only copied once. // the ami is only copied once.
stepAMIRegionCopy = StepAMIRegionCopy{ stepAMIRegionCopy = StepAMIRegionCopy{
AccessConfig: testAccessConfig(), AccessConfig: FakeAccessConfig(),
Regions: []string{"us-east-1"}, Regions: []string{"us-east-1"},
Name: "fake-ami-name", Name: "fake-ami-name",
OriginalRegion: "us-east-1", OriginalRegion: "us-east-1",
@ -152,7 +152,7 @@ func TestStepAMIRegionCopy_duplicates(t *testing.T) {
// the ami is only copied once. // the ami is only copied once.
stepAMIRegionCopy = StepAMIRegionCopy{ stepAMIRegionCopy = StepAMIRegionCopy{
AccessConfig: testAccessConfig(), AccessConfig: FakeAccessConfig(),
Regions: []string{"us-east-1"}, Regions: []string{"us-east-1"},
EncryptBootVolume: config.TriFalse, EncryptBootVolume: config.TriFalse,
Name: "fake-ami-name", Name: "fake-ami-name",
@ -174,7 +174,7 @@ func TestStepAMIRegionCopy_duplicates(t *testing.T) {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
stepAMIRegionCopy = StepAMIRegionCopy{ stepAMIRegionCopy = StepAMIRegionCopy{
AccessConfig: testAccessConfig(), AccessConfig: FakeAccessConfig(),
// Many duplicates for only 3 actual values // Many duplicates for only 3 actual values
Regions: []string{"us-east-1", "us-west-2", "us-west-2", "ap-east-1", "ap-east-1", "ap-east-1"}, Regions: []string{"us-east-1", "us-west-2", "us-west-2", "ap-east-1", "ap-east-1", "ap-east-1"},
AMIKmsKeyId: "IlikePancakes", AMIKmsKeyId: "IlikePancakes",
@ -203,7 +203,7 @@ func TestStepAMIRegionCopy_duplicates(t *testing.T) {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
stepAMIRegionCopy = StepAMIRegionCopy{ stepAMIRegionCopy = StepAMIRegionCopy{
AccessConfig: testAccessConfig(), AccessConfig: FakeAccessConfig(),
// Many duplicates for only 3 actual values // Many duplicates for only 3 actual values
Regions: []string{"us-east-1", "us-west-2", "us-west-2", "ap-east-1", "ap-east-1", "ap-east-1"}, Regions: []string{"us-east-1", "us-west-2", "us-west-2", "ap-east-1", "ap-east-1", "ap-east-1"},
Name: "fake-ami-name", Name: "fake-ami-name",
@ -223,7 +223,7 @@ func TestStepAMIRegionCopy_duplicates(t *testing.T) {
func TestStepAmiRegionCopy_nil_encryption(t *testing.T) { func TestStepAmiRegionCopy_nil_encryption(t *testing.T) {
// create step // create step
stepAMIRegionCopy := StepAMIRegionCopy{ stepAMIRegionCopy := StepAMIRegionCopy{
AccessConfig: testAccessConfig(), AccessConfig: FakeAccessConfig(),
Regions: make([]string, 0), Regions: make([]string, 0),
AMIKmsKeyId: "", AMIKmsKeyId: "",
RegionKeyIds: make(map[string]string), RegionKeyIds: make(map[string]string),
@ -249,7 +249,7 @@ func TestStepAmiRegionCopy_nil_encryption(t *testing.T) {
func TestStepAmiRegionCopy_true_encryption(t *testing.T) { func TestStepAmiRegionCopy_true_encryption(t *testing.T) {
// create step // create step
stepAMIRegionCopy := StepAMIRegionCopy{ stepAMIRegionCopy := StepAMIRegionCopy{
AccessConfig: testAccessConfig(), AccessConfig: FakeAccessConfig(),
Regions: make([]string, 0), Regions: make([]string, 0),
AMIKmsKeyId: "", AMIKmsKeyId: "",
RegionKeyIds: make(map[string]string), RegionKeyIds: make(map[string]string),
@ -275,7 +275,7 @@ func TestStepAmiRegionCopy_true_encryption(t *testing.T) {
func TestStepAmiRegionCopy_nil_intermediary(t *testing.T) { func TestStepAmiRegionCopy_nil_intermediary(t *testing.T) {
// create step // create step
stepAMIRegionCopy := StepAMIRegionCopy{ stepAMIRegionCopy := StepAMIRegionCopy{
AccessConfig: testAccessConfig(), AccessConfig: FakeAccessConfig(),
Regions: make([]string, 0), Regions: make([]string, 0),
AMIKmsKeyId: "", AMIKmsKeyId: "",
RegionKeyIds: make(map[string]string), RegionKeyIds: make(map[string]string),
@ -303,7 +303,7 @@ func TestStepAmiRegionCopy_AMISkipBuildRegion(t *testing.T) {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
stepAMIRegionCopy := StepAMIRegionCopy{ stepAMIRegionCopy := StepAMIRegionCopy{
AccessConfig: testAccessConfig(), AccessConfig: FakeAccessConfig(),
Regions: []string{"us-west-1"}, Regions: []string{"us-west-1"},
AMIKmsKeyId: "", AMIKmsKeyId: "",
RegionKeyIds: map[string]string{"us-west-1": "abcde"}, RegionKeyIds: map[string]string{"us-west-1": "abcde"},
@ -329,7 +329,7 @@ func TestStepAmiRegionCopy_AMISkipBuildRegion(t *testing.T) {
// skip build region is false. // skip build region is false.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
stepAMIRegionCopy = StepAMIRegionCopy{ stepAMIRegionCopy = StepAMIRegionCopy{
AccessConfig: testAccessConfig(), AccessConfig: FakeAccessConfig(),
Regions: []string{"us-west-1"}, Regions: []string{"us-west-1"},
AMIKmsKeyId: "", AMIKmsKeyId: "",
RegionKeyIds: make(map[string]string), RegionKeyIds: make(map[string]string),
@ -354,7 +354,7 @@ func TestStepAmiRegionCopy_AMISkipBuildRegion(t *testing.T) {
// skip build region is false, but encrypt is true // skip build region is false, but encrypt is true
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
stepAMIRegionCopy = StepAMIRegionCopy{ stepAMIRegionCopy = StepAMIRegionCopy{
AccessConfig: testAccessConfig(), AccessConfig: FakeAccessConfig(),
Regions: []string{"us-west-1"}, Regions: []string{"us-west-1"},
AMIKmsKeyId: "", AMIKmsKeyId: "",
RegionKeyIds: map[string]string{"us-west-1": "abcde"}, RegionKeyIds: map[string]string{"us-west-1": "abcde"},
@ -380,7 +380,7 @@ func TestStepAmiRegionCopy_AMISkipBuildRegion(t *testing.T) {
// skip build region is true, and encrypt is true // skip build region is true, and encrypt is true
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
stepAMIRegionCopy = StepAMIRegionCopy{ stepAMIRegionCopy = StepAMIRegionCopy{
AccessConfig: testAccessConfig(), AccessConfig: FakeAccessConfig(),
Regions: []string{"us-west-1"}, Regions: []string{"us-west-1"},
AMIKmsKeyId: "", AMIKmsKeyId: "",
RegionKeyIds: map[string]string{"us-west-1": "abcde"}, RegionKeyIds: map[string]string{"us-west-1": "abcde"},

View File

@ -0,0 +1,25 @@
package common
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
)
type mockEC2Client struct {
ec2iface.EC2API
}
func FakeAccessConfig() *AccessConfig {
accessConfig := AccessConfig{
getEC2Connection: func() ec2iface.EC2API {
return &mockEC2Client{}
},
PollingConfig: new(AWSPollingConfig),
}
accessConfig.session = session.Must(session.NewSession(&aws.Config{
Region: aws.String("us-west-1"),
}))
return &accessConfig
}

View File

@ -317,7 +317,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
&stepSnapshotEBSVolumes{ &stepSnapshotEBSVolumes{
PollingConfig: b.config.PollingConfig, PollingConfig: b.config.PollingConfig,
VolumeMapping: b.config.VolumeMappings, VolumeMapping: b.config.VolumeMappings,
AccessConfig: b.config.AccessConfig, AccessConfig: &b.config.AccessConfig,
Ctx: b.config.ctx, Ctx: b.config.ctx,
}, },
} }

View File

@ -7,18 +7,18 @@ import (
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/aws/aws-sdk-go/service/ec2/ec2iface"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer-plugin-sdk/multistep" "github.com/hashicorp/packer-plugin-sdk/multistep"
"github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/template/interpolate" "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
) )
type stepSnapshotEBSVolumes struct { type stepSnapshotEBSVolumes struct {
PollingConfig *awscommon.AWSPollingConfig PollingConfig *awscommon.AWSPollingConfig
AccessConfig awscommon.AccessConfig AccessConfig *awscommon.AccessConfig
VolumeMapping []BlockDevice VolumeMapping []BlockDevice
//Map of SnapshotID: BlockDevice, Where *BlockDevice is in VolumeMapping //Map of SnapshotID: BlockDevice, Where *BlockDevice is in VolumeMapping
SnapshotMap map[string]*BlockDevice snapshotMap map[string]*BlockDevice
Ctx interpolate.Context Ctx interpolate.Context
} }
@ -27,7 +27,7 @@ func (s *stepSnapshotEBSVolumes) Run(ctx context.Context, state multistep.StateB
instance := state.Get("instance").(*ec2.Instance) instance := state.Get("instance").(*ec2.Instance)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
s.SnapshotMap = make(map[string]*BlockDevice) s.snapshotMap = make(map[string]*BlockDevice)
for _, instanceBlockDevices := range instance.BlockDeviceMappings { for _, instanceBlockDevices := range instance.BlockDeviceMappings {
for _, configVolumeMapping := range s.VolumeMapping { for _, configVolumeMapping := range s.VolumeMapping {
@ -72,13 +72,13 @@ func (s *stepSnapshotEBSVolumes) Run(ctx context.Context, state multistep.StateB
return multistep.ActionHalt return multistep.ActionHalt
} }
ui.Message(fmt.Sprintf("Requested Snapshot of Volume %s: %s", *instanceBlockDevices.Ebs.VolumeId, *snapshot.SnapshotId)) ui.Message(fmt.Sprintf("Requested Snapshot of Volume %s: %s", *instanceBlockDevices.Ebs.VolumeId, *snapshot.SnapshotId))
s.SnapshotMap[*snapshot.SnapshotId] = &configVolumeMapping s.snapshotMap[*snapshot.SnapshotId] = &configVolumeMapping
} }
} }
} }
ui.Say("Waiting for Snapshots to become ready...") ui.Say("Waiting for Snapshots to become ready...")
for snapID := range s.SnapshotMap { for snapID := range s.snapshotMap {
ui.Message(fmt.Sprintf("Waiting for %s to be ready.", snapID)) ui.Message(fmt.Sprintf("Waiting for %s to be ready.", snapID))
err := s.PollingConfig.WaitUntilSnapshotDone(ctx, ec2conn, snapID) err := s.PollingConfig.WaitUntilSnapshotDone(ctx, ec2conn, snapID)
if err != nil { if err != nil {
@ -93,7 +93,7 @@ func (s *stepSnapshotEBSVolumes) Run(ctx context.Context, state multistep.StateB
//Attach User and Group permissions to snapshots //Attach User and Group permissions to snapshots
ui.Say("Setting User/Group Permissions for Snapshots...") ui.Say("Setting User/Group Permissions for Snapshots...")
for snapID, bd := range s.SnapshotMap { for snapID, bd := range s.snapshotMap {
snapshotOptions := make(map[string]*ec2.ModifySnapshotAttributeInput) snapshotOptions := make(map[string]*ec2.ModifySnapshotAttributeInput)
if len(bd.SnapshotGroups) > 0 { if len(bd.SnapshotGroups) > 0 {
@ -151,7 +151,7 @@ func (s *stepSnapshotEBSVolumes) Run(ctx context.Context, state multistep.StateB
snapshots := make(EbsSnapshots) snapshots := make(EbsSnapshots)
currentregion := s.AccessConfig.SessionRegion() currentregion := s.AccessConfig.SessionRegion()
for snapID := range s.SnapshotMap { for snapID := range s.snapshotMap {
snapshots[currentregion] = append( snapshots[currentregion] = append(
snapshots[currentregion], snapshots[currentregion],
snapID) snapID)

View File

@ -7,11 +7,13 @@ import (
"testing" "testing"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
//"github.com/aws/aws-sdk-go/service/ec2" //"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer-plugin-sdk/multistep" "github.com/hashicorp/packer-plugin-sdk/multistep"
"github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/builder/amazon/common"
) )
// Define a mock struct to be used in unit tests for common aws steps. // Define a mock struct to be used in unit tests for common aws steps.
@ -76,17 +78,43 @@ func TestStepSnapshot_run_simple(t *testing.T) {
} }
state := tState(t) state := tState(t)
state.Put("instance", &ec2.Instance{
InstanceId: aws.String("instance-id"),
})
accessConfig := common.FakeAccessConfig()
volMap := BlockDevices{
{
awscommon.BlockDevice `mapstructure:",squash"`
// Key/value pair tags to apply to the volume. These are retained after the builder
// completes. This is a [template engine](/docs/templates/legacy_json_templates/engine), see
// [Build template data](#build-template-data) for more information.
Tags map[string]string `mapstructure:"tags" required:"false"`
// Same as [`tags`](#tags) but defined as a singular repeatable block
// containing a `key` and a `value` field. In HCL2 mode the
// [`dynamic_block`](/docs/templates/hcl_templates/expressions#dynamic-blocks)
// will allow you to create those programatically.
Tag config.KeyValues `mapstructure:"tag" required:"false"`
// Create a Snapshot of this Volume.
SnapshotVolume bool `mapstructure:"snapshot_volume" required:"false"`
awscommon.SnapshotConfig `mapstructure:",squash"`
}
}
//Todo add fake volumes, for the snap shot step to Snapshot //Todo add fake volumes, for the snap shot step to Snapshot
step := stepSnapshotEBSVolumes{ step := stepSnapshotEBSVolumes{
PollingConfig: new(common.AWSPollingConfig), //Dosnt look like builder sets this up PollingConfig: new(common.AWSPollingConfig), //Dosnt look like builder sets this up
AccessConfig: accessConfig,
VolumeMapping: b.config.VolumeMappings, VolumeMapping: b.config.VolumeMappings,
Ctx: b.config.ctx, Ctx: b.config.ctx,
} }
step.Run(context.Background(), state) step.Run(context.Background(), state)
if len(step.SnapshotMap) != 1 { if len(step.snapshotMap) != 1 {
t.Fatalf("Missing Snapshot from step") t.Fatalf("Missing Snapshot from step")
} }
} }