2017-03-03 03:56:17 -05:00
|
|
|
package ecs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"fmt"
|
2017-06-01 20:14:51 -04:00
|
|
|
|
2017-03-03 03:56:17 -05:00
|
|
|
"github.com/denverdino/aliyungo/common"
|
|
|
|
"github.com/denverdino/aliyungo/ecs"
|
2017-04-17 09:04:52 -04:00
|
|
|
builderT "github.com/hashicorp/packer/helper/builder/testing"
|
|
|
|
"github.com/hashicorp/packer/packer"
|
2017-03-03 03:56:17 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestBuilderAcc_basic(t *testing.T) {
|
|
|
|
builderT.Test(t, builderT.TestCase{
|
|
|
|
PreCheck: func() {
|
|
|
|
testAccPreCheck(t)
|
|
|
|
},
|
|
|
|
Builder: &Builder{},
|
|
|
|
Template: testBuilderAccBasic,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-05-25 06:27:54 -04:00
|
|
|
//func TestBuilderAcc_windows(t *testing.T) {
|
|
|
|
// builderT.Test(t, builderT.TestCase{
|
|
|
|
// PreCheck: func() {
|
|
|
|
// testAccPreCheck(t)
|
|
|
|
// },
|
|
|
|
// Builder: &Builder{},
|
|
|
|
// Template: testBuilderAccWindows,
|
|
|
|
// })
|
|
|
|
//}
|
2017-03-03 03:56:17 -05:00
|
|
|
|
2017-05-25 21:54:07 -04:00
|
|
|
//func TestBuilderAcc_regionCopy(t *testing.T) {
|
|
|
|
// builderT.Test(t, builderT.TestCase{
|
|
|
|
// PreCheck: func() {
|
|
|
|
// testAccPreCheck(t)
|
|
|
|
// },
|
|
|
|
// Builder: &Builder{},
|
|
|
|
// Template: testBuilderAccRegionCopy,
|
|
|
|
// Check: checkRegionCopy([]string{"cn-hangzhou", "cn-shenzhen"}),
|
|
|
|
// })
|
|
|
|
//}
|
2017-03-03 03:56:17 -05:00
|
|
|
|
|
|
|
func TestBuilderAcc_forceDelete(t *testing.T) {
|
|
|
|
// Build the same alicloud image twice, with ecs_image_force_delete on the second run
|
|
|
|
builderT.Test(t, builderT.TestCase{
|
|
|
|
PreCheck: func() {
|
|
|
|
testAccPreCheck(t)
|
|
|
|
},
|
|
|
|
Builder: &Builder{},
|
|
|
|
Template: buildForceDeregisterConfig("false", "delete"),
|
|
|
|
SkipArtifactTeardown: true,
|
|
|
|
})
|
|
|
|
|
|
|
|
builderT.Test(t, builderT.TestCase{
|
|
|
|
PreCheck: func() {
|
|
|
|
testAccPreCheck(t)
|
|
|
|
},
|
|
|
|
Builder: &Builder{},
|
|
|
|
Template: buildForceDeregisterConfig("true", "delete"),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBuilderAcc_ECSImageSharing(t *testing.T) {
|
|
|
|
builderT.Test(t, builderT.TestCase{
|
|
|
|
PreCheck: func() {
|
|
|
|
testAccPreCheck(t)
|
|
|
|
},
|
|
|
|
Builder: &Builder{},
|
|
|
|
Template: testBuilderAccSharing,
|
|
|
|
Check: checkECSImageSharing("1309208528360047"),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBuilderAcc_forceDeleteSnapshot(t *testing.T) {
|
|
|
|
destImageName := "delete"
|
|
|
|
|
|
|
|
// Build the same alicloud image name twice, with force_delete_snapshot on the second run
|
|
|
|
builderT.Test(t, builderT.TestCase{
|
|
|
|
PreCheck: func() {
|
|
|
|
testAccPreCheck(t)
|
|
|
|
},
|
|
|
|
Builder: &Builder{},
|
|
|
|
Template: buildForceDeleteSnapshotConfig("false", destImageName),
|
|
|
|
SkipArtifactTeardown: true,
|
|
|
|
})
|
|
|
|
|
|
|
|
// Get image data by image image name
|
|
|
|
client, _ := testAliyunClient()
|
|
|
|
images, _, _ := client.DescribeImages(&ecs.DescribeImagesArgs{
|
|
|
|
ImageName: "packer-test-" + destImageName,
|
|
|
|
RegionId: common.Region("cn-beijing")})
|
|
|
|
|
|
|
|
image := images[0]
|
|
|
|
|
|
|
|
// Get snapshot ids for image
|
|
|
|
snapshotIds := []string{}
|
|
|
|
for _, device := range image.DiskDeviceMappings.DiskDeviceMapping {
|
|
|
|
if device.Device != "" && device.SnapshotId != "" {
|
|
|
|
snapshotIds = append(snapshotIds, device.SnapshotId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
builderT.Test(t, builderT.TestCase{
|
|
|
|
PreCheck: func() {
|
|
|
|
testAccPreCheck(t)
|
|
|
|
},
|
|
|
|
Builder: &Builder{},
|
|
|
|
Template: buildForceDeleteSnapshotConfig("true", destImageName),
|
|
|
|
Check: checkSnapshotsDeleted(snapshotIds),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-09-16 06:16:13 -04:00
|
|
|
func TestBuilderAcc_imageTags(t *testing.T) {
|
|
|
|
builderT.Test(t, builderT.TestCase{
|
|
|
|
PreCheck: func() {
|
|
|
|
testAccPreCheck(t)
|
|
|
|
},
|
|
|
|
Builder: &Builder{},
|
|
|
|
Template: testBuilderAccImageTags,
|
|
|
|
Check: checkImageTags(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-03-03 03:56:17 -05:00
|
|
|
func checkSnapshotsDeleted(snapshotIds []string) builderT.TestCheckFunc {
|
|
|
|
return func(artifacts []packer.Artifact) error {
|
|
|
|
// Verify the snapshots are gone
|
|
|
|
client, _ := testAliyunClient()
|
|
|
|
snapshotResp, _, err := client.DescribeSnapshots(
|
|
|
|
&ecs.DescribeSnapshotsArgs{RegionId: common.Region("cn-beijing"), SnapshotIds: snapshotIds},
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Query snapshot failed %v", err)
|
|
|
|
}
|
|
|
|
if len(snapshotResp) > 0 {
|
2017-05-25 22:59:53 -04:00
|
|
|
return fmt.Errorf("Snapshots weren't successfully deleted by " +
|
|
|
|
"`ecs_image_force_delete_snapshots`")
|
2017-03-03 03:56:17 -05:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkECSImageSharing(uid string) builderT.TestCheckFunc {
|
|
|
|
return func(artifacts []packer.Artifact) error {
|
|
|
|
if len(artifacts) > 1 {
|
|
|
|
return fmt.Errorf("more than 1 artifact")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the actual *Artifact pointer so we can access the AMIs directly
|
|
|
|
artifactRaw := artifacts[0]
|
|
|
|
artifact, ok := artifactRaw.(*Artifact)
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("unknown artifact: %#v", artifactRaw)
|
|
|
|
}
|
|
|
|
|
|
|
|
// describe the image, get block devices with a snapshot
|
|
|
|
client, _ := testAliyunClient()
|
2017-05-25 22:59:53 -04:00
|
|
|
imageSharePermissionResponse, err := client.DescribeImageSharePermission(
|
|
|
|
&ecs.ModifyImageSharePermissionArgs{
|
|
|
|
RegionId: "cn-beijing",
|
|
|
|
ImageId: artifact.AlicloudImages["cn-beijing"],
|
|
|
|
})
|
2017-03-03 03:56:17 -05:00
|
|
|
|
|
|
|
if err != nil {
|
2017-05-25 22:59:53 -04:00
|
|
|
return fmt.Errorf("Error retrieving Image Attributes for ECS Image Artifact (%#v) "+
|
|
|
|
"in ECS Image Sharing Test: %s", artifact, err)
|
2017-03-03 03:56:17 -05:00
|
|
|
}
|
|
|
|
|
2017-05-25 22:59:53 -04:00
|
|
|
if len(imageSharePermissionResponse.Accounts.Account) != 1 &&
|
|
|
|
imageSharePermissionResponse.Accounts.Account[0].AliyunId != uid {
|
|
|
|
return fmt.Errorf("share account is incorrect %d",
|
|
|
|
len(imageSharePermissionResponse.Accounts.Account))
|
2017-03-03 03:56:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkRegionCopy(regions []string) builderT.TestCheckFunc {
|
|
|
|
return func(artifacts []packer.Artifact) error {
|
|
|
|
if len(artifacts) > 1 {
|
|
|
|
return fmt.Errorf("more than 1 artifact")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the actual *Artifact pointer so we can access the AMIs directly
|
|
|
|
artifactRaw := artifacts[0]
|
|
|
|
artifact, ok := artifactRaw.(*Artifact)
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("unknown artifact: %#v", artifactRaw)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that we copied to only the regions given
|
|
|
|
regionSet := make(map[string]struct{})
|
|
|
|
for _, r := range regions {
|
|
|
|
regionSet[r] = struct{}{}
|
|
|
|
}
|
|
|
|
for r := range artifact.AlicloudImages {
|
|
|
|
if r == "cn-beijing" {
|
|
|
|
delete(regionSet, r)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if _, ok := regionSet[r]; !ok {
|
|
|
|
return fmt.Errorf("unknown region: %s", r)
|
|
|
|
}
|
|
|
|
|
|
|
|
delete(regionSet, r)
|
|
|
|
}
|
|
|
|
if len(regionSet) > 0 {
|
|
|
|
return fmt.Errorf("didn't copy to: %#v", regionSet)
|
|
|
|
}
|
|
|
|
client, _ := testAliyunClient()
|
|
|
|
for key, value := range artifact.AlicloudImages {
|
|
|
|
client.WaitForImageReady(common.Region(key), value, 1800)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-16 06:16:13 -04:00
|
|
|
func checkImageTags() builderT.TestCheckFunc {
|
|
|
|
return func(artifacts []packer.Artifact) error {
|
|
|
|
if len(artifacts) > 1 {
|
|
|
|
return fmt.Errorf("more than 1 artifact")
|
|
|
|
}
|
|
|
|
// Get the actual *Artifact pointer so we can access the AMIs directly
|
|
|
|
artifactRaw := artifacts[0]
|
|
|
|
artifact, ok := artifactRaw.(*Artifact)
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("unknown artifact: %#v", artifactRaw)
|
|
|
|
}
|
|
|
|
// describe the image, get block devices with a snapshot
|
|
|
|
client, _ := testAliyunClient()
|
|
|
|
tags, _, err := client.DescribeTags(
|
|
|
|
&ecs.DescribeTagsArgs{
|
|
|
|
RegionId: "cn-beijing",
|
|
|
|
ResourceType: ecs.TagResourceImage,
|
|
|
|
ResourceId: artifact.AlicloudImages["cn-beijing"],
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error retrieving Image Attributes for ECS Image Artifact (%#v) "+
|
|
|
|
"in ECS Image Tags Test: %s", artifact, err)
|
|
|
|
}
|
|
|
|
failed := false
|
|
|
|
if len(tags) != 2 {
|
|
|
|
failed = true
|
|
|
|
}
|
|
|
|
if !failed {
|
|
|
|
for i := 0; i < len(tags); i++ {
|
|
|
|
if tags[i].TagKey == "TagKey1" && tags[i].TagValue != "TagValue1" {
|
|
|
|
failed = true
|
|
|
|
} else if tags[i].TagKey == "TagKey2" && tags[i].TagValue != "TagValue2" {
|
|
|
|
failed = true
|
|
|
|
} else if tags[i].TagKey != "TagKey1" && tags[i].TagKey != "TagKey2" {
|
|
|
|
failed = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if failed {
|
|
|
|
return fmt.Errorf("tags is not correctly set %#v", tags)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-03 03:56:17 -05:00
|
|
|
func testAccPreCheck(t *testing.T) {
|
|
|
|
if v := os.Getenv("ALICLOUD_ACCESS_KEY"); v == "" {
|
|
|
|
t.Fatal("ALICLOUD_ACCESS_KEY must be set for acceptance tests")
|
|
|
|
}
|
|
|
|
|
|
|
|
if v := os.Getenv("ALICLOUD_SECRET_KEY"); v == "" {
|
|
|
|
t.Fatal("ALICLOUD_SECRET_KEY must be set for acceptance tests")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func testAliyunClient() (*ecs.Client, error) {
|
|
|
|
access := &AlicloudAccessConfig{AlicloudRegion: "cn-beijing"}
|
|
|
|
err := access.Config()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
client, err := access.Client()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return client, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
const testBuilderAccBasic = `
|
|
|
|
{ "builders": [{
|
|
|
|
"type": "test",
|
|
|
|
"region": "cn-beijing",
|
|
|
|
"instance_type": "ecs.n1.tiny",
|
2018-09-18 09:40:57 -04:00
|
|
|
"source_image":"ubuntu_16_0402_64_20G_alibase_20180409.vhd",
|
2017-03-03 03:56:17 -05:00
|
|
|
"io_optimized":"true",
|
|
|
|
"ssh_username":"root",
|
|
|
|
"image_name": "packer-test_{{timestamp}}"
|
|
|
|
}]
|
|
|
|
}`
|
|
|
|
|
|
|
|
const testBuilderAccRegionCopy = `
|
|
|
|
{
|
|
|
|
"builders": [{
|
|
|
|
"type": "test",
|
|
|
|
"region": "cn-beijing",
|
|
|
|
"instance_type": "ecs.n1.tiny",
|
2017-05-25 21:54:07 -04:00
|
|
|
"source_image":"ubuntu_16_0402_64_40G_base_20170222.vhd",
|
2017-03-03 03:56:17 -05:00
|
|
|
"io_optimized":"true",
|
|
|
|
"ssh_username":"root",
|
|
|
|
"image_name": "packer-test_{{timestamp}}",
|
|
|
|
"image_copy_regions": ["cn-hangzhou", "cn-shenzhen"]
|
|
|
|
}]
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
|
|
|
const testBuilderAccForceDelete = `
|
|
|
|
{
|
|
|
|
"builders": [{
|
|
|
|
"type": "test",
|
|
|
|
"region": "cn-beijing",
|
|
|
|
"instance_type": "ecs.n1.tiny",
|
2017-05-25 21:54:07 -04:00
|
|
|
"source_image":"ubuntu_16_0402_64_40G_base_20170222.vhd",
|
2017-03-03 03:56:17 -05:00
|
|
|
"io_optimized":"true",
|
|
|
|
"ssh_username":"root",
|
|
|
|
"image_force_delete": "%s",
|
|
|
|
"image_name": "packer-test_%s"
|
|
|
|
}]
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
|
|
|
const testBuilderAccForceDeleteSnapshot = `
|
|
|
|
{
|
|
|
|
"builders": [{
|
|
|
|
"type": "test",
|
|
|
|
"region": "cn-beijing",
|
|
|
|
"instance_type": "ecs.n1.tiny",
|
2017-05-25 21:54:07 -04:00
|
|
|
"source_image":"ubuntu_16_0402_64_40G_base_20170222.vhd",
|
2017-03-03 03:56:17 -05:00
|
|
|
"io_optimized":"true",
|
|
|
|
"ssh_username":"root",
|
|
|
|
"image_force_delete_snapshots": "%s",
|
|
|
|
"image_force_delete": "%s",
|
|
|
|
"image_name": "packer-test-%s"
|
|
|
|
}]
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
|
|
|
// share with catsby
|
|
|
|
const testBuilderAccSharing = `
|
|
|
|
{
|
|
|
|
"builders": [{
|
|
|
|
"type": "test",
|
|
|
|
"region": "cn-beijing",
|
|
|
|
"instance_type": "ecs.n1.tiny",
|
2017-05-25 21:54:07 -04:00
|
|
|
"source_image":"ubuntu_16_0402_64_40G_base_20170222.vhd",
|
2017-03-03 03:56:17 -05:00
|
|
|
"io_optimized":"true",
|
|
|
|
"ssh_username":"root",
|
|
|
|
"image_name": "packer-test_{{timestamp}}",
|
|
|
|
"image_share_account":["1309208528360047"]
|
|
|
|
}]
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
2018-09-16 06:16:13 -04:00
|
|
|
const testBuilderAccImageTags = `
|
|
|
|
{ "builders": [{
|
|
|
|
"type": "test",
|
|
|
|
"region": "cn-beijing",
|
|
|
|
"instance_type": "ecs.n1.tiny",
|
|
|
|
"source_image":"ubuntu_16_0402_64_20G_alibase_20180409.vhd",
|
|
|
|
"ssh_username": "root",
|
|
|
|
"io_optimized":"true",
|
|
|
|
"image_name": "packer-test_{{timestamp}}",
|
|
|
|
"tags": {
|
|
|
|
"TagKey1": "TagValue1",
|
|
|
|
"TagKey2": "TagValue2"
|
|
|
|
}
|
|
|
|
}]
|
|
|
|
}`
|
|
|
|
|
2017-03-03 03:56:17 -05:00
|
|
|
func buildForceDeregisterConfig(val, name string) string {
|
|
|
|
return fmt.Sprintf(testBuilderAccForceDelete, val, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func buildForceDeleteSnapshotConfig(val, name string) string {
|
|
|
|
return fmt.Sprintf(testBuilderAccForceDeleteSnapshot, val, val, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
const testBuilderAccWindows = `
|
|
|
|
{ "builders": [{
|
|
|
|
"type": "test",
|
|
|
|
"region": "cn-beijing",
|
|
|
|
"instance_type": "ecs.n1.tiny",
|
2017-04-17 09:04:52 -04:00
|
|
|
"source_image":"win2008_64_ent_r2_zh-cn_40G_alibase_20170301.vhd",
|
2017-03-03 03:56:17 -05:00
|
|
|
"io_optimized":"true",
|
|
|
|
"image_force_delete":"true",
|
|
|
|
"communicator": "winrm",
|
|
|
|
"winrm_port": 5985,
|
|
|
|
"winrm_username": "Administrator",
|
|
|
|
"winrm_password": "Test1234",
|
|
|
|
"image_name": "packer-test_{{timestamp}}"
|
|
|
|
}]
|
|
|
|
}`
|