github.phpd.cn/hashicorp/packer@v1.3.2/builder/amazon/ebs/builder_acc_test.go (about) 1 /* 2 Deregister the test image with 3 aws ec2 deregister-image --image-id $(aws ec2 describe-images --output text --filters "Name=name,Values=packer-test-packer-test-dereg" --query 'Images[*].{ID:ImageId}') 4 */ 5 package ebs 6 7 import ( 8 "fmt" 9 "testing" 10 11 "github.com/aws/aws-sdk-go/aws" 12 "github.com/aws/aws-sdk-go/service/ec2" 13 "github.com/hashicorp/packer/builder/amazon/common" 14 builderT "github.com/hashicorp/packer/helper/builder/testing" 15 "github.com/hashicorp/packer/packer" 16 ) 17 18 func TestBuilderAcc_basic(t *testing.T) { 19 builderT.Test(t, builderT.TestCase{ 20 PreCheck: func() { testAccPreCheck(t) }, 21 Builder: &Builder{}, 22 Template: testBuilderAccBasic, 23 }) 24 } 25 26 func TestBuilderAcc_regionCopy(t *testing.T) { 27 builderT.Test(t, builderT.TestCase{ 28 PreCheck: func() { testAccPreCheck(t) }, 29 Builder: &Builder{}, 30 Template: testBuilderAccRegionCopy, 31 Check: checkRegionCopy([]string{"us-east-1", "us-west-2"}), 32 }) 33 } 34 35 func TestBuilderAcc_forceDeregister(t *testing.T) { 36 // Build the same AMI name twice, with force_deregister on the second run 37 builderT.Test(t, builderT.TestCase{ 38 PreCheck: func() { testAccPreCheck(t) }, 39 Builder: &Builder{}, 40 Template: buildForceDeregisterConfig("false", "dereg"), 41 SkipArtifactTeardown: true, 42 }) 43 44 builderT.Test(t, builderT.TestCase{ 45 PreCheck: func() { testAccPreCheck(t) }, 46 Builder: &Builder{}, 47 Template: buildForceDeregisterConfig("true", "dereg"), 48 }) 49 } 50 51 func TestBuilderAcc_forceDeleteSnapshot(t *testing.T) { 52 amiName := "packer-test-dereg" 53 54 // Build the same AMI name twice, with force_delete_snapshot on the second run 55 builderT.Test(t, builderT.TestCase{ 56 PreCheck: func() { testAccPreCheck(t) }, 57 Builder: &Builder{}, 58 Template: buildForceDeleteSnapshotConfig("false", amiName), 59 SkipArtifactTeardown: true, 60 }) 61 62 // Get image data by AMI name 63 ec2conn, _ := testEC2Conn() 64 describeInput := &ec2.DescribeImagesInput{Filters: []*ec2.Filter{ 65 { 66 Name: aws.String("name"), 67 Values: []*string{aws.String(amiName)}, 68 }, 69 }} 70 ec2conn.WaitUntilImageExists(describeInput) 71 imageResp, _ := ec2conn.DescribeImages(describeInput) 72 image := imageResp.Images[0] 73 74 // Get snapshot ids for image 75 snapshotIds := []*string{} 76 for _, device := range image.BlockDeviceMappings { 77 if device.Ebs != nil && device.Ebs.SnapshotId != nil { 78 snapshotIds = append(snapshotIds, device.Ebs.SnapshotId) 79 } 80 } 81 82 builderT.Test(t, builderT.TestCase{ 83 PreCheck: func() { testAccPreCheck(t) }, 84 Builder: &Builder{}, 85 Template: buildForceDeleteSnapshotConfig("true", amiName), 86 Check: checkSnapshotsDeleted(snapshotIds), 87 }) 88 } 89 90 func checkSnapshotsDeleted(snapshotIds []*string) builderT.TestCheckFunc { 91 return func(artifacts []packer.Artifact) error { 92 // Verify the snapshots are gone 93 ec2conn, _ := testEC2Conn() 94 snapshotResp, _ := ec2conn.DescribeSnapshots( 95 &ec2.DescribeSnapshotsInput{SnapshotIds: snapshotIds}, 96 ) 97 98 if len(snapshotResp.Snapshots) > 0 { 99 return fmt.Errorf("Snapshots weren't successfully deleted by `force_delete_snapshot`") 100 } 101 return nil 102 } 103 } 104 105 func TestBuilderAcc_amiSharing(t *testing.T) { 106 builderT.Test(t, builderT.TestCase{ 107 PreCheck: func() { testAccPreCheck(t) }, 108 Builder: &Builder{}, 109 Template: testBuilderAccSharing, 110 Check: checkAMISharing(2, "932021504756", "all"), 111 }) 112 } 113 114 func TestBuilderAcc_encryptedBoot(t *testing.T) { 115 builderT.Test(t, builderT.TestCase{ 116 PreCheck: func() { testAccPreCheck(t) }, 117 Builder: &Builder{}, 118 Template: testBuilderAccEncrypted, 119 Check: checkBootEncrypted(), 120 }) 121 } 122 123 func checkAMISharing(count int, uid, group string) builderT.TestCheckFunc { 124 return func(artifacts []packer.Artifact) error { 125 if len(artifacts) > 1 { 126 return fmt.Errorf("more than 1 artifact") 127 } 128 129 // Get the actual *Artifact pointer so we can access the AMIs directly 130 artifactRaw := artifacts[0] 131 artifact, ok := artifactRaw.(*common.Artifact) 132 if !ok { 133 return fmt.Errorf("unknown artifact: %#v", artifactRaw) 134 } 135 136 // describe the image, get block devices with a snapshot 137 ec2conn, _ := testEC2Conn() 138 imageResp, err := ec2conn.DescribeImageAttribute(&ec2.DescribeImageAttributeInput{ 139 Attribute: aws.String("launchPermission"), 140 ImageId: aws.String(artifact.Amis["us-east-1"]), 141 }) 142 143 if err != nil { 144 return fmt.Errorf("Error retrieving Image Attributes for AMI Artifact (%#v) in AMI Sharing Test: %s", artifact, err) 145 } 146 147 // Launch Permissions are in addition to the userid that created it, so if 148 // you add 3 additional ami_users, you expect 2 Launch Permissions here 149 if len(imageResp.LaunchPermissions) != count { 150 return fmt.Errorf("Error in Image Attributes, expected (%d) Launch Permissions, got (%d)", count, len(imageResp.LaunchPermissions)) 151 } 152 153 userFound := false 154 for _, lp := range imageResp.LaunchPermissions { 155 if lp.UserId != nil && uid == *lp.UserId { 156 userFound = true 157 } 158 } 159 160 if !userFound { 161 return fmt.Errorf("Error in Image Attributes, expected User ID (%s) to have Launch Permissions, but was not found", uid) 162 } 163 164 groupFound := false 165 for _, lp := range imageResp.LaunchPermissions { 166 if lp.Group != nil && group == *lp.Group { 167 groupFound = true 168 } 169 } 170 171 if !groupFound { 172 return fmt.Errorf("Error in Image Attributes, expected Group ID (%s) to have Launch Permissions, but was not found", group) 173 } 174 175 return nil 176 } 177 } 178 179 func checkRegionCopy(regions []string) builderT.TestCheckFunc { 180 return func(artifacts []packer.Artifact) error { 181 if len(artifacts) > 1 { 182 return fmt.Errorf("more than 1 artifact") 183 } 184 185 // Get the actual *Artifact pointer so we can access the AMIs directly 186 artifactRaw := artifacts[0] 187 artifact, ok := artifactRaw.(*common.Artifact) 188 if !ok { 189 return fmt.Errorf("unknown artifact: %#v", artifactRaw) 190 } 191 192 // Verify that we copied to only the regions given 193 regionSet := make(map[string]struct{}) 194 for _, r := range regions { 195 regionSet[r] = struct{}{} 196 } 197 for r := range artifact.Amis { 198 if _, ok := regionSet[r]; !ok { 199 return fmt.Errorf("unknown region: %s", r) 200 } 201 202 delete(regionSet, r) 203 } 204 if len(regionSet) > 0 { 205 return fmt.Errorf("didn't copy to: %#v", regionSet) 206 } 207 208 return nil 209 } 210 } 211 212 func checkBootEncrypted() builderT.TestCheckFunc { 213 return func(artifacts []packer.Artifact) error { 214 215 // Get the actual *Artifact pointer so we can access the AMIs directly 216 artifactRaw := artifacts[0] 217 artifact, ok := artifactRaw.(*common.Artifact) 218 if !ok { 219 return fmt.Errorf("unknown artifact: %#v", artifactRaw) 220 } 221 222 // describe the image, get block devices with a snapshot 223 ec2conn, _ := testEC2Conn() 224 imageResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ 225 ImageIds: []*string{aws.String(artifact.Amis["us-east-1"])}, 226 }) 227 228 if err != nil { 229 return fmt.Errorf("Error retrieving Image Attributes for AMI (%s) in AMI Encrypted Boot Test: %s", artifact, err) 230 } 231 232 image := imageResp.Images[0] // Only requested a single AMI ID 233 234 rootDeviceName := image.RootDeviceName 235 236 for _, bd := range image.BlockDeviceMappings { 237 if *bd.DeviceName == *rootDeviceName { 238 if *bd.Ebs.Encrypted != true { 239 return fmt.Errorf("volume not encrypted: %s", *bd.Ebs.SnapshotId) 240 } 241 } 242 } 243 244 return nil 245 } 246 } 247 248 func testAccPreCheck(t *testing.T) { 249 } 250 251 func testEC2Conn() (*ec2.EC2, error) { 252 access := &common.AccessConfig{RawRegion: "us-east-1"} 253 session, err := access.Session() 254 if err != nil { 255 return nil, err 256 } 257 258 return ec2.New(session), nil 259 } 260 261 const testBuilderAccBasic = ` 262 { 263 "builders": [{ 264 "type": "test", 265 "region": "us-east-1", 266 "instance_type": "m3.medium", 267 "source_ami": "ami-76b2a71e", 268 "ssh_username": "ubuntu", 269 "ami_name": "packer-test {{timestamp}}" 270 }] 271 } 272 ` 273 274 const testBuilderAccRegionCopy = ` 275 { 276 "builders": [{ 277 "type": "test", 278 "region": "us-east-1", 279 "instance_type": "m3.medium", 280 "source_ami": "ami-76b2a71e", 281 "ssh_username": "ubuntu", 282 "ami_name": "packer-test {{timestamp}}", 283 "ami_regions": ["us-east-1", "us-west-2"] 284 }] 285 } 286 ` 287 288 const testBuilderAccForceDeregister = ` 289 { 290 "builders": [{ 291 "type": "test", 292 "region": "us-east-1", 293 "instance_type": "m3.medium", 294 "source_ami": "ami-76b2a71e", 295 "ssh_username": "ubuntu", 296 "force_deregister": "%s", 297 "ami_name": "%s" 298 }] 299 } 300 ` 301 302 const testBuilderAccForceDeleteSnapshot = ` 303 { 304 "builders": [{ 305 "type": "test", 306 "region": "us-east-1", 307 "instance_type": "m3.medium", 308 "source_ami": "ami-76b2a71e", 309 "ssh_username": "ubuntu", 310 "force_deregister": "%s", 311 "force_delete_snapshot": "%s", 312 "ami_name": "%s" 313 }] 314 } 315 ` 316 317 // share with catsby 318 const testBuilderAccSharing = ` 319 { 320 "builders": [{ 321 "type": "test", 322 "region": "us-east-1", 323 "instance_type": "m3.medium", 324 "source_ami": "ami-76b2a71e", 325 "ssh_username": "ubuntu", 326 "ami_name": "packer-test {{timestamp}}", 327 "ami_users":["932021504756"], 328 "ami_groups":["all"] 329 }] 330 } 331 ` 332 333 const testBuilderAccEncrypted = ` 334 { 335 "builders": [{ 336 "type": "test", 337 "region": "us-east-1", 338 "instance_type": "m3.medium", 339 "source_ami":"ami-c15bebaa", 340 "ssh_username": "ubuntu", 341 "ami_name": "packer-enc-test {{timestamp}}", 342 "encrypt_boot": true 343 }] 344 } 345 ` 346 347 func buildForceDeregisterConfig(val, name string) string { 348 return fmt.Sprintf(testBuilderAccForceDeregister, val, name) 349 } 350 351 func buildForceDeleteSnapshotConfig(val, name string) string { 352 return fmt.Sprintf(testBuilderAccForceDeleteSnapshot, val, val, name) 353 }