github.com/angdraug/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  }