171 lines
4.3 KiB
Go
171 lines
4.3 KiB
Go
package ebsvolume
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/aws/request"
|
|
|
|
//"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/multistep"
|
|
"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.
|
|
type mockEC2Conn struct {
|
|
ec2iface.EC2API
|
|
Config *aws.Config
|
|
}
|
|
|
|
func (m *mockEC2Conn) CreateSnapshot(input *ec2.CreateSnapshotInput) (*ec2.Snapshot, error) {
|
|
snap := &ec2.Snapshot{
|
|
// This isn't typical amazon format, but injecting the volume id into
|
|
// this field lets us verify that the right volume was snapshotted with
|
|
// a simple string comparison
|
|
SnapshotId: aws.String(fmt.Sprintf("snap-of-%s", *input.VolumeId)),
|
|
}
|
|
|
|
return snap, nil
|
|
}
|
|
|
|
func (m *mockEC2Conn) WaitUntilSnapshotCompletedWithContext(aws.Context, *ec2.DescribeSnapshotsInput, ...request.WaiterOption) error {
|
|
return nil
|
|
}
|
|
|
|
func getMockConn(config *common.AccessConfig, target string) (ec2iface.EC2API, error) {
|
|
mockConn := &mockEC2Conn{
|
|
Config: aws.NewConfig(),
|
|
}
|
|
return mockConn, nil
|
|
}
|
|
|
|
// Create statebag for running test
|
|
func tState(t *testing.T) multistep.StateBag {
|
|
state := new(multistep.BasicStateBag)
|
|
state.Put("ui", &packer.BasicUi{
|
|
Reader: new(bytes.Buffer),
|
|
Writer: new(bytes.Buffer),
|
|
})
|
|
// state.Put("amis", map[string]string{"us-east-1": "ami-12345"})
|
|
// state.Put("snapshots", map[string][]string{"us-east-1": {"snap-0012345"}})
|
|
conn, _ := getMockConn(&common.AccessConfig{}, "us-east-2")
|
|
|
|
state.Put("ec2", conn)
|
|
// Store a fake instance that contains a block device that matches the
|
|
// volumes defined in the config above
|
|
state.Put("instance", &ec2.Instance{
|
|
InstanceId: aws.String("instance-id"),
|
|
BlockDeviceMappings: []*ec2.InstanceBlockDeviceMapping{
|
|
{
|
|
DeviceName: aws.String("/dev/xvda"),
|
|
Ebs: &ec2.EbsInstanceBlockDevice{
|
|
VolumeId: aws.String("vol-1234"),
|
|
},
|
|
},
|
|
{
|
|
DeviceName: aws.String("/dev/xvdb"),
|
|
Ebs: &ec2.EbsInstanceBlockDevice{
|
|
VolumeId: aws.String("vol-5678"),
|
|
},
|
|
},
|
|
},
|
|
})
|
|
return state
|
|
}
|
|
|
|
func TestStepSnapshot_run_simple(t *testing.T) {
|
|
var b Builder
|
|
config := testConfig() //from builder_test
|
|
|
|
//Set some snapshot settings
|
|
config["ebs_volumes"] = []map[string]interface{}{
|
|
{
|
|
"device_name": "/dev/xvdb",
|
|
"volume_size": "32",
|
|
"delete_on_termination": true,
|
|
"snapshot_volume": true,
|
|
},
|
|
}
|
|
|
|
generatedData, warnings, err := b.Prepare(config)
|
|
if len(warnings) > 0 {
|
|
t.Fatalf("bad: %#v", warnings)
|
|
}
|
|
if err != nil {
|
|
t.Fatalf("should not have error: %s", err)
|
|
}
|
|
if len(generatedData) == 0 {
|
|
t.Fatalf("Generated data should not be empty")
|
|
}
|
|
|
|
state := tState(t)
|
|
|
|
accessConfig := common.FakeAccessConfig()
|
|
|
|
step := stepSnapshotEBSVolumes{
|
|
PollingConfig: new(common.AWSPollingConfig),
|
|
AccessConfig: accessConfig,
|
|
VolumeMapping: b.config.VolumeMappings,
|
|
Ctx: b.config.ctx,
|
|
}
|
|
|
|
step.Run(context.Background(), state)
|
|
|
|
if len(step.snapshotMap) != 1 {
|
|
t.Fatalf("Missing Snapshot from step")
|
|
}
|
|
|
|
if volmapping := step.snapshotMap["snap-of-vol-5678"]; volmapping == nil {
|
|
t.Fatalf("Didn't snapshot correct volume: Map is %#v", step.snapshotMap)
|
|
}
|
|
}
|
|
|
|
func TestStepSnapshot_run_no_snaps(t *testing.T) {
|
|
var b Builder
|
|
config := testConfig() //from builder_test
|
|
|
|
//Set some snapshot settings
|
|
config["ebs_volumes"] = []map[string]interface{}{
|
|
{
|
|
"device_name": "/dev/xvdb",
|
|
"volume_size": "32",
|
|
"delete_on_termination": true,
|
|
"snapshot_volume": false,
|
|
},
|
|
}
|
|
|
|
generatedData, warnings, err := b.Prepare(config)
|
|
if len(warnings) > 0 {
|
|
t.Fatalf("bad: %#v", warnings)
|
|
}
|
|
if err != nil {
|
|
t.Fatalf("should not have error: %s", err)
|
|
}
|
|
if len(generatedData) == 0 {
|
|
t.Fatalf("Generated data should not be empty")
|
|
}
|
|
|
|
state := tState(t)
|
|
|
|
accessConfig := common.FakeAccessConfig()
|
|
|
|
step := stepSnapshotEBSVolumes{
|
|
PollingConfig: new(common.AWSPollingConfig),
|
|
AccessConfig: accessConfig,
|
|
VolumeMapping: b.config.VolumeMappings,
|
|
Ctx: b.config.ctx,
|
|
}
|
|
|
|
step.Run(context.Background(), state)
|
|
|
|
if len(step.snapshotMap) != 0 {
|
|
t.Fatalf("Shouldn't have snapshotted any volumes")
|
|
}
|
|
}
|