func (s *StepSourceAMIInfo) Run(state multistep.StateBag) multistep.StepAction {
	config := state.Get("config").(*Config)
	ec2conn := state.Get("ec2").(ec2.EC2)
	ui := state.Get("ui").(packer.Ui)

	ui.Say("Inspecting the source AMI...")
	imageResp, err := ec2conn.Images([]string{config.SourceAmi}, ec2.NewFilter())
	if err != nil {
		err := fmt.Errorf("Error querying AMI: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	if len(imageResp.Images) == 0 {
		err := fmt.Errorf("Source AMI '%s' was not found!", config.SourceAmi)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	image := &imageResp.Images[0]

	// It must be EBS-backed otherwise the build won't work
	if image.RootDeviceType != "ebs" {
		err := fmt.Errorf("The root device of the source AMI must be EBS-backed.")
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	state.Put("source_image", image)
	return multistep.ActionContinue
}
Exemple #2
0
func (s *S) TestDescribeInstancesExample1(c *C) {
	testServer.Response(200, nil, DescribeInstancesExample1)

	filter := ec2.NewFilter()
	filter.Add("key1", "value1")
	filter.Add("key2", "value2", "value3")

	resp, err := s.ec2.Instances([]string{"i-1", "i-2"}, nil)

	req := testServer.WaitRequest()
	c.Assert(req.Form["Action"], DeepEquals, []string{"DescribeInstances"})
	c.Assert(req.Form["InstanceId.1"], DeepEquals, []string{"i-1"})
	c.Assert(req.Form["InstanceId.2"], DeepEquals, []string{"i-2"})

	c.Assert(err, IsNil)
	c.Assert(resp.RequestId, Equals, "98e3c9a4-848c-4d6d-8e8a-b1bdEXAMPLE")
	c.Assert(resp.Reservations, HasLen, 2)

	r0 := resp.Reservations[0]
	c.Assert(r0.ReservationId, Equals, "r-b27e30d9")
	c.Assert(r0.OwnerId, Equals, "999988887777")
	c.Assert(r0.RequesterId, Equals, "854251627541")
	c.Assert(r0.SecurityGroups, DeepEquals, []ec2.SecurityGroup{{Name: "default", Id: "sg-67ad940e"}})
	c.Assert(r0.Instances, HasLen, 1)

	r0i := r0.Instances[0]
	c.Assert(r0i.InstanceId, Equals, "i-c5cd56af")
	c.Assert(r0i.PrivateDNSName, Equals, "domU-12-31-39-10-56-34.compute-1.internal")
	c.Assert(r0i.DNSName, Equals, "ec2-174-129-165-232.compute-1.amazonaws.com")
	c.Assert(r0i.AvailZone, Equals, "us-east-1b")
}
Exemple #3
0
func (s *S) TestDescribeSecurityGroupsExampleWithFilter(c *C) {
	testServer.Response(200, nil, DescribeSecurityGroupsExample)

	filter := ec2.NewFilter()
	filter.Add("ip-permission.protocol", "tcp")
	filter.Add("ip-permission.from-port", "22")
	filter.Add("ip-permission.to-port", "22")
	filter.Add("ip-permission.group-name", "app_server_group", "database_group")

	_, err := s.ec2.SecurityGroups(nil, filter)

	req := testServer.WaitRequest()
	c.Assert(req.Form["Action"], DeepEquals, []string{"DescribeSecurityGroups"})
	c.Assert(req.Form["Filter.1.Name"], DeepEquals, []string{"ip-permission.from-port"})
	c.Assert(req.Form["Filter.1.Value.1"], DeepEquals, []string{"22"})
	c.Assert(req.Form["Filter.2.Name"], DeepEquals, []string{"ip-permission.group-name"})
	c.Assert(req.Form["Filter.2.Value.1"], DeepEquals, []string{"app_server_group"})
	c.Assert(req.Form["Filter.2.Value.2"], DeepEquals, []string{"database_group"})
	c.Assert(req.Form["Filter.3.Name"], DeepEquals, []string{"ip-permission.protocol"})
	c.Assert(req.Form["Filter.3.Value.1"], DeepEquals, []string{"tcp"})
	c.Assert(req.Form["Filter.4.Name"], DeepEquals, []string{"ip-permission.to-port"})
	c.Assert(req.Form["Filter.4.Value.1"], DeepEquals, []string{"22"})

	c.Assert(err, IsNil)
}
Exemple #4
0
// SSHAddress returns a function that can be given to the SSH communicator
// for determining the SSH address based on the instance DNS name.
func SSHAddress(e ec2.EC2, port int) func(multistep.StateBag) (string, error) {
	return func(state multistep.StateBag) (string, error) {
		for j := 0; j < 2; j++ {
			var host string
			i := state.Get("instance").(*ec2.Instance)
			if i.DNSName != "" {
				host = i.DNSName
			} else if i.VpcId != "" {
				host = i.PrivateIpAddress
			}

			if host != "" {
				return fmt.Sprintf("%s:%d", host, port), nil
			}

			r, err := e.Instances([]string{i.InstanceId}, ec2.NewFilter())
			if err != nil {
				return "", err
			}

			if len(r.Reservations) == 0 || len(r.Reservations[0].Instances) == 0 {
				return "", fmt.Errorf("instance not found: %s", i.InstanceId)
			}

			state.Put("instance", &r.Reservations[0].Instances[0])
			time.Sleep(1 * time.Second)
		}

		return "", errors.New("couldn't determine IP address for instance")
	}
}
Exemple #5
0
func (s *StepAttachVolume) Run(state multistep.StateBag) multistep.StepAction {
	ec2conn := state.Get("ec2").(ec2.EC2)
	device := state.Get("device").(string)
	instance := state.Get("instance").(*ec2.Instance)
	ui := state.Get("ui").(packer.Ui)
	volumeId := state.Get("volume_id").(string)

	// For the API call, it expects "sd" prefixed devices.
	attachVolume := strings.Replace(device, "/xvd", "/sd", 1)

	ui.Say(fmt.Sprintf("Attaching the root volume to %s", attachVolume))
	_, err := ec2conn.AttachVolume(volumeId, instance.InstanceId, attachVolume)
	if err != nil {
		err := fmt.Errorf("Error attaching volume: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	// Mark that we attached it so we can detach it later
	s.attached = true
	s.volumeId = volumeId

	// Wait for the volume to become attached
	stateChange := awscommon.StateChangeConf{
		Conn:      ec2conn,
		Pending:   []string{"attaching"},
		StepState: state,
		Target:    "attached",
		Refresh: func() (interface{}, string, error) {
			resp, err := ec2conn.Volumes([]string{volumeId}, ec2.NewFilter())
			if err != nil {
				return nil, "", err
			}

			if len(resp.Volumes[0].Attachments) == 0 {
				return nil, "", errors.New("No attachments on volume.")
			}

			a := resp.Volumes[0].Attachments[0]
			return a, a.Status, nil
		},
	}

	_, err = awscommon.WaitForState(&stateChange)
	if err != nil {
		err := fmt.Errorf("Error waiting for volume: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	state.Put("attach_cleanup", s)
	return multistep.ActionContinue
}
Exemple #6
0
func (s *StepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
	ec2conn := state.Get("ec2").(ec2.EC2)
	ui := state.Get("ui").(packer.Ui)
	volumeId := state.Get("volume_id").(string)

	ui.Say("Creating snapshot...")
	createSnapResp, err := ec2conn.CreateSnapshot(volumeId, "")
	if err != nil {
		err := fmt.Errorf("Error creating snapshot: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	// Set the snapshot ID so we can delete it later
	s.snapshotId = createSnapResp.Id
	ui.Message(fmt.Sprintf("Snapshot ID: %s", s.snapshotId))

	// Wait for the snapshot to be ready
	stateChange := awscommon.StateChangeConf{
		Conn:      ec2conn,
		Pending:   []string{"pending"},
		StepState: state,
		Target:    "completed",
		Refresh: func() (interface{}, string, error) {
			resp, err := ec2conn.Snapshots([]string{s.snapshotId}, ec2.NewFilter())
			if err != nil {
				return nil, "", err
			}

			if len(resp.Snapshots) == 0 {
				return nil, "", errors.New("No snapshots found.")
			}

			s := resp.Snapshots[0]
			return s, s.Status, nil
		},
	}

	_, err = awscommon.WaitForState(&stateChange)
	if err != nil {
		err := fmt.Errorf("Error waiting for snapshot: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	state.Put("snapshot_id", s.snapshotId)
	return multistep.ActionContinue
}
Exemple #7
0
func (s *S) TestDescribeImagesExample(c *C) {
	testServer.Response(200, nil, DescribeImagesExample)

	filter := ec2.NewFilter()
	filter.Add("key1", "value1")
	filter.Add("key2", "value2", "value3")

	resp, err := s.ec2.Images([]string{"ami-1", "ami-2"}, filter)

	req := testServer.WaitRequest()
	c.Assert(req.Form["Action"], DeepEquals, []string{"DescribeImages"})
	c.Assert(req.Form["ImageId.1"], DeepEquals, []string{"ami-1"})
	c.Assert(req.Form["ImageId.2"], DeepEquals, []string{"ami-2"})
	c.Assert(req.Form["Filter.1.Name"], DeepEquals, []string{"key1"})
	c.Assert(req.Form["Filter.1.Value.1"], DeepEquals, []string{"value1"})
	c.Assert(req.Form["Filter.1.Value.2"], IsNil)
	c.Assert(req.Form["Filter.2.Name"], DeepEquals, []string{"key2"})
	c.Assert(req.Form["Filter.2.Value.1"], DeepEquals, []string{"value2"})
	c.Assert(req.Form["Filter.2.Value.2"], DeepEquals, []string{"value3"})

	c.Assert(err, IsNil)
	c.Assert(resp.RequestId, Equals, "4a4a27a2-2e7c-475d-b35b-ca822EXAMPLE")
	c.Assert(resp.Images, HasLen, 1)

	i0 := resp.Images[0]
	c.Assert(i0.Id, Equals, "ami-a2469acf")
	c.Assert(i0.Type, Equals, "machine")
	c.Assert(i0.Name, Equals, "example-marketplace-amzn-ami.1")
	c.Assert(i0.Description, Equals, "Amazon Linux AMI i386 EBS")
	c.Assert(i0.Location, Equals, "aws-marketplace/example-marketplace-amzn-ami.1")
	c.Assert(i0.State, Equals, "available")
	c.Assert(i0.Public, Equals, true)
	c.Assert(i0.OwnerId, Equals, "123456789999")
	c.Assert(i0.OwnerAlias, Equals, "aws-marketplace")
	c.Assert(i0.Architecture, Equals, "i386")
	c.Assert(i0.KernelId, Equals, "aki-805ea7e9")
	c.Assert(i0.RootDeviceType, Equals, "ebs")
	c.Assert(i0.RootDeviceName, Equals, "/dev/sda1")
	c.Assert(i0.VirtualizationType, Equals, "paravirtual")
	c.Assert(i0.Hypervisor, Equals, "xen")

	c.Assert(i0.BlockDevices, HasLen, 1)
	c.Assert(i0.BlockDevices[0].DeviceName, Equals, "/dev/sda1")
	c.Assert(i0.BlockDevices[0].SnapshotId, Equals, "snap-787e9403")
	c.Assert(i0.BlockDevices[0].VolumeSize, Equals, int64(8))
	c.Assert(i0.BlockDevices[0].DeleteOnTermination, Equals, true)
}
Exemple #8
0
func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error {
	if !s.attached {
		return nil
	}

	ec2conn := state.Get("ec2").(ec2.EC2)
	ui := state.Get("ui").(packer.Ui)

	ui.Say("Detaching EBS volume...")
	_, err := ec2conn.DetachVolume(s.volumeId)
	if err != nil {
		return fmt.Errorf("Error detaching EBS volume: %s", err)
	}

	s.attached = false

	// Wait for the volume to detach
	stateChange := awscommon.StateChangeConf{
		Conn:      ec2conn,
		Pending:   []string{"attaching", "attached", "detaching"},
		StepState: state,
		Target:    "detached",
		Refresh: func() (interface{}, string, error) {
			resp, err := ec2conn.Volumes([]string{s.volumeId}, ec2.NewFilter())
			if err != nil {
				return nil, "", err
			}

			v := resp.Volumes[0]
			if len(v.Attachments) > 0 {
				return v, v.Attachments[0].Status, nil
			} else {
				return v, "detached", nil
			}
		},
	}

	_, err = awscommon.WaitForState(&stateChange)
	if err != nil {
		return fmt.Errorf("Error waiting for volume: %s", err)
	}

	return nil
}
Exemple #9
0
func (s *StepInstanceInfo) Run(state multistep.StateBag) multistep.StepAction {
	ec2conn := state.Get("ec2").(ec2.EC2)
	ui := state.Get("ui").(packer.Ui)

	// Get our own instance ID
	ui.Say("Gathering information about this EC2 instance...")
	instanceIdBytes, err := aws.GetMetaData("instance-id")
	if err != nil {
		log.Printf("Error: %s", err)
		err := fmt.Errorf(
			"Error retrieving the ID of the instance Packer is running on.\n" +
				"Please verify Packer is running on a proper AWS EC2 instance.")
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	instanceId := string(instanceIdBytes)
	log.Printf("Instance ID: %s", instanceId)

	// Query the entire instance metadata
	instancesResp, err := ec2conn.Instances([]string{instanceId}, ec2.NewFilter())
	if err != nil {
		err := fmt.Errorf("Error getting instance data: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	if len(instancesResp.Reservations) == 0 {
		err := fmt.Errorf("Error getting instance data: no instance found.")
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	instance := &instancesResp.Reservations[0].Instances[0]
	state.Put("instance", instance)

	return multistep.ActionContinue
}
Exemple #10
0
func (s *S) TestDescribeSnapshotsExample(c *C) {
	testServer.Response(200, nil, DescribeSnapshotsExample)

	filter := ec2.NewFilter()
	filter.Add("key1", "value1")
	filter.Add("key2", "value2", "value3")

	resp, err := s.ec2.Snapshots([]string{"snap-1", "snap-2"}, filter)

	req := testServer.WaitRequest()
	c.Assert(req.Form["Action"], DeepEquals, []string{"DescribeSnapshots"})
	c.Assert(req.Form["SnapshotId.1"], DeepEquals, []string{"snap-1"})
	c.Assert(req.Form["SnapshotId.2"], DeepEquals, []string{"snap-2"})
	c.Assert(req.Form["Filter.1.Name"], DeepEquals, []string{"key1"})
	c.Assert(req.Form["Filter.1.Value.1"], DeepEquals, []string{"value1"})
	c.Assert(req.Form["Filter.1.Value.2"], IsNil)
	c.Assert(req.Form["Filter.2.Name"], DeepEquals, []string{"key2"})
	c.Assert(req.Form["Filter.2.Value.1"], DeepEquals, []string{"value2"})
	c.Assert(req.Form["Filter.2.Value.2"], DeepEquals, []string{"value3"})

	c.Assert(err, IsNil)
	c.Assert(resp.RequestId, Equals, "59dbff89-35bd-4eac-99ed-be587EXAMPLE")
	c.Assert(resp.Snapshots, HasLen, 1)

	s0 := resp.Snapshots[0]
	c.Assert(s0.Id, Equals, "snap-1a2b3c4d")
	c.Assert(s0.VolumeId, Equals, "vol-8875daef")
	c.Assert(s0.VolumeSize, Equals, "15")
	c.Assert(s0.Status, Equals, "pending")
	c.Assert(s0.StartTime, Equals, "2010-07-29T04:12:01.000Z")
	c.Assert(s0.Progress, Equals, "30%")
	c.Assert(s0.OwnerId, Equals, "111122223333")
	c.Assert(s0.Description, Equals, "Daily Backup")

	c.Assert(s0.Tags, HasLen, 1)
	c.Assert(s0.Tags[0].Key, Equals, "Purpose")
	c.Assert(s0.Tags[0].Value, Equals, "demo_db_14_backup")
}
Exemple #11
0
// InstanceStateRefreshFunc returns a StateRefreshFunc that is used to watch
// an EC2 instance.
func InstanceStateRefreshFunc(conn ec2.EC2, i *ec2.Instance) StateRefreshFunc {
	return func() (interface{}, string, error) {
		resp, err := conn.Instances([]string{i.InstanceId}, ec2.NewFilter())
		if err != nil {
			if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidInstanceID.NotFound" {
				// Set this to nil as if we didn't find anything.
				resp = nil
			} else {
				log.Printf("Error on InstanceStateRefresh: %s", err)
				return nil, "", err
			}
		}

		if resp == nil || len(resp.Reservations) == 0 || len(resp.Reservations[0].Instances) == 0 {
			// Sometimes AWS just has consistency issues and doesn't see
			// our instance yet. Return an empty state.
			return nil, "", nil
		}

		i = &resp.Reservations[0].Instances[0]
		return i, i.State.Name, nil
	}
}
Exemple #12
0
// AMIStateRefreshFunc returns a StateRefreshFunc that is used to watch
// an AMI for state changes.
func AMIStateRefreshFunc(conn ec2.EC2, imageId string) StateRefreshFunc {
	return func() (interface{}, string, error) {
		resp, err := conn.Images([]string{imageId}, ec2.NewFilter())
		if err != nil {
			if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidAMIID.NotFound" {
				// Set this to nil as if we didn't find anything.
				resp = nil
			} else {
				log.Printf("Error on AMIStateRefresh: %s", err)
				return nil, "", err
			}
		}

		if resp == nil || len(resp.Images) == 0 {
			// Sometimes AWS has consistency issues and doesn't see the
			// AMI. Return an empty state.
			return nil, "", nil
		}

		i := resp.Images[0]
		return i, i.State, nil
	}
}
Exemple #13
0
func (s *S) TestDescribeInstancesExample2(c *C) {
	testServer.Response(200, nil, DescribeInstancesExample2)

	filter := ec2.NewFilter()
	filter.Add("key1", "value1")
	filter.Add("key2", "value2", "value3")

	resp, err := s.ec2.Instances([]string{"i-1", "i-2"}, filter)

	req := testServer.WaitRequest()
	c.Assert(req.Form["Action"], DeepEquals, []string{"DescribeInstances"})
	c.Assert(req.Form["InstanceId.1"], DeepEquals, []string{"i-1"})
	c.Assert(req.Form["InstanceId.2"], DeepEquals, []string{"i-2"})
	c.Assert(req.Form["Filter.1.Name"], DeepEquals, []string{"key1"})
	c.Assert(req.Form["Filter.1.Value.1"], DeepEquals, []string{"value1"})
	c.Assert(req.Form["Filter.1.Value.2"], IsNil)
	c.Assert(req.Form["Filter.2.Name"], DeepEquals, []string{"key2"})
	c.Assert(req.Form["Filter.2.Value.1"], DeepEquals, []string{"value2"})
	c.Assert(req.Form["Filter.2.Value.2"], DeepEquals, []string{"value3"})

	c.Assert(err, IsNil)
	c.Assert(resp.RequestId, Equals, "59dbff89-35bd-4eac-99ed-be587EXAMPLE")
	c.Assert(resp.Reservations, HasLen, 1)

	r0 := resp.Reservations[0]
	r0i := r0.Instances[0]
	c.Assert(r0i.State.Code, Equals, 16)
	c.Assert(r0i.State.Name, Equals, "running")

	r0t0 := r0i.Tags[0]
	r0t1 := r0i.Tags[1]
	c.Assert(r0t0.Key, Equals, "webserver")
	c.Assert(r0t0.Value, Equals, "")
	c.Assert(r0t1.Key, Equals, "stack")
	c.Assert(r0t1.Value, Equals, "Production")
}
Exemple #14
0
func (s *ServerTests) TestGroupFiltering(c *C) {
	g := make([]ec2.SecurityGroup, 4)
	for i := range g {
		resp, err := s.ec2.CreateSecurityGroup(ec2.SecurityGroup{Name: sessionName(fmt.Sprintf("testgroup%d", i)), Description: fmt.Sprintf("testdescription%d", i)})
		c.Assert(err, IsNil)
		g[i] = resp.SecurityGroup
		c.Logf("group %d: %v", i, g[i])
		defer s.ec2.DeleteSecurityGroup(g[i])
	}

	perms := [][]ec2.IPPerm{
		{{
			Protocol:  "tcp",
			FromPort:  100,
			ToPort:    200,
			SourceIPs: []string{"1.2.3.4/32"},
		}},
		{{
			Protocol:     "tcp",
			FromPort:     200,
			ToPort:       300,
			SourceGroups: []ec2.UserSecurityGroup{{Id: g[1].Id}},
		}},
		{{
			Protocol:     "udp",
			FromPort:     200,
			ToPort:       400,
			SourceGroups: []ec2.UserSecurityGroup{{Id: g[1].Id}},
		}},
	}
	for i, ps := range perms {
		_, err := s.ec2.AuthorizeSecurityGroup(g[i], ps)
		c.Assert(err, IsNil)
	}

	groups := func(indices ...int) (gs []ec2.SecurityGroup) {
		for _, index := range indices {
			gs = append(gs, g[index])
		}
		return
	}

	type groupTest struct {
		about      string
		groups     []ec2.SecurityGroup // groupIds argument to SecurityGroups method.
		filters    []filterSpec        // filters argument to SecurityGroups method.
		results    []ec2.SecurityGroup // set of expected result groups.
		allowExtra bool                // specified results may be incomplete.
		err        string              // expected error.
	}
	filterCheck := func(name, val string, gs []ec2.SecurityGroup) groupTest {
		return groupTest{
			about:      "filter check " + name,
			filters:    []filterSpec{{name, []string{val}}},
			results:    gs,
			allowExtra: true,
		}
	}
	tests := []groupTest{
		{
			about:      "check that SecurityGroups returns all groups",
			results:    groups(0, 1, 2, 3),
			allowExtra: true,
		}, {
			about:   "check that specifying two group ids returns them",
			groups:  idsOnly(groups(0, 2)),
			results: groups(0, 2),
		}, {
			about:   "check that specifying names only works",
			groups:  namesOnly(groups(0, 2)),
			results: groups(0, 2),
		}, {
			about:  "check that specifying a non-existent group id gives an error",
			groups: append(groups(0), ec2.SecurityGroup{Id: "sg-eeeeeeeee"}),
			err:    `.*\(InvalidGroup\.NotFound\)`,
		}, {
			about: "check that a filter allowed two groups returns both of them",
			filters: []filterSpec{
				{"group-id", []string{g[0].Id, g[2].Id}},
			},
			results: groups(0, 2),
		},
		{
			about:  "check that the previous filter works when specifying a list of ids",
			groups: groups(1, 2),
			filters: []filterSpec{
				{"group-id", []string{g[0].Id, g[2].Id}},
			},
			results: groups(2),
		}, {
			about: "check that a filter allowing no groups returns none",
			filters: []filterSpec{
				{"group-id", []string{"sg-eeeeeeeee"}},
			},
		},
		filterCheck("description", "testdescription1", groups(1)),
		filterCheck("group-name", g[2].Name, groups(2)),
		filterCheck("ip-permission.cidr", "1.2.3.4/32", groups(0)),
		filterCheck("ip-permission.group-name", g[1].Name, groups(1, 2)),
		filterCheck("ip-permission.protocol", "udp", groups(2)),
		filterCheck("ip-permission.from-port", "200", groups(1, 2)),
		filterCheck("ip-permission.to-port", "200", groups(0)),
		// TODO owner-id
	}
	for i, t := range tests {
		c.Logf("%d. %s", i, t.about)
		var f *ec2.Filter
		if t.filters != nil {
			f = ec2.NewFilter()
			for _, spec := range t.filters {
				f.Add(spec.name, spec.values...)
			}
		}
		resp, err := s.ec2.SecurityGroups(t.groups, f)
		if t.err != "" {
			c.Check(err, ErrorMatches, t.err)
			continue
		}
		c.Assert(err, IsNil)
		groups := make(map[string]*ec2.SecurityGroup)
		for j := range resp.Groups {
			group := &resp.Groups[j].SecurityGroup
			c.Check(groups[group.Id], IsNil, Commentf("duplicate group id: %q", group.Id))

			groups[group.Id] = group
		}
		// If extra groups may be returned, eliminate all groups that
		// we did not create in this session apart from the default group.
		if t.allowExtra {
			namePat := regexp.MustCompile(sessionName("testgroup[0-9]"))
			for id, g := range groups {
				if !namePat.MatchString(g.Name) {
					delete(groups, id)
				}
			}
		}
		c.Check(groups, HasLen, len(t.results))
		for j, g := range t.results {
			rg := groups[g.Id]
			c.Assert(rg, NotNil, Commentf("group %d (%v) not found; got %#v", j, g, groups))
			c.Check(rg.Name, Equals, g.Name, Commentf("group %d (%v)", j, g))
		}
	}
}
Exemple #15
0
func (s *ServerTests) TestInstanceFiltering(c *C) {
	groupResp, err := s.ec2.CreateSecurityGroup(ec2.SecurityGroup{Name: sessionName("testgroup1"), Description: "testgroup one description"})
	c.Assert(err, IsNil)
	group1 := groupResp.SecurityGroup
	defer s.ec2.DeleteSecurityGroup(group1)

	groupResp, err = s.ec2.CreateSecurityGroup(ec2.SecurityGroup{Name: sessionName("testgroup2"), Description: "testgroup two description"})
	c.Assert(err, IsNil)
	group2 := groupResp.SecurityGroup
	defer s.ec2.DeleteSecurityGroup(group2)

	insts := make([]*ec2.Instance, 3)
	inst, err := s.ec2.RunInstances(&ec2.RunInstances{
		MinCount:       2,
		ImageId:        imageId,
		InstanceType:   "t1.micro",
		SecurityGroups: []ec2.SecurityGroup{group1},
	})
	c.Assert(err, IsNil)
	insts[0] = &inst.Instances[0]
	insts[1] = &inst.Instances[1]
	defer terminateInstances(c, s.ec2, insts)

	imageId2 := "ami-e358958a" // Natty server, i386, EBS store
	inst, err = s.ec2.RunInstances(&ec2.RunInstances{
		ImageId:        imageId2,
		InstanceType:   "t1.micro",
		SecurityGroups: []ec2.SecurityGroup{group2},
	})
	c.Assert(err, IsNil)
	insts[2] = &inst.Instances[0]

	ids := func(indices ...int) (instIds []string) {
		for _, index := range indices {
			instIds = append(instIds, insts[index].InstanceId)
		}
		return
	}

	tests := []struct {
		about       string
		instanceIds []string     // instanceIds argument to Instances method.
		filters     []filterSpec // filters argument to Instances method.
		resultIds   []string     // set of instance ids of expected results.
		allowExtra  bool         // resultIds may be incomplete.
		err         string       // expected error.
	}{
		{
			about:      "check that Instances returns all instances",
			resultIds:  ids(0, 1, 2),
			allowExtra: true,
		}, {
			about:       "check that specifying two instance ids returns them",
			instanceIds: ids(0, 2),
			resultIds:   ids(0, 2),
		}, {
			about:       "check that specifying a non-existent instance id gives an error",
			instanceIds: append(ids(0), "i-deadbeef"),
			err:         `.*\(InvalidInstanceID\.NotFound\)`,
		}, {
			about: "check that a filter allowed both instances returns both of them",
			filters: []filterSpec{
				{"instance-id", ids(0, 2)},
			},
			resultIds: ids(0, 2),
		}, {
			about: "check that a filter allowing only one instance returns it",
			filters: []filterSpec{
				{"instance-id", ids(1)},
			},
			resultIds: ids(1),
		}, {
			about: "check that a filter allowing no instances returns none",
			filters: []filterSpec{
				{"instance-id", []string{"i-deadbeef12345"}},
			},
		}, {
			about: "check that filtering on group id works",
			filters: []filterSpec{
				{"group-id", []string{group1.Id}},
			},
			resultIds: ids(0, 1),
		}, {
			about: "check that filtering on group name works",
			filters: []filterSpec{
				{"group-name", []string{group1.Name}},
			},
			resultIds: ids(0, 1),
		}, {
			about: "check that filtering on image id works",
			filters: []filterSpec{
				{"image-id", []string{imageId}},
			},
			resultIds:  ids(0, 1),
			allowExtra: true,
		}, {
			about: "combination filters 1",
			filters: []filterSpec{
				{"image-id", []string{imageId, imageId2}},
				{"group-name", []string{group1.Name}},
			},
			resultIds: ids(0, 1),
		}, {
			about: "combination filters 2",
			filters: []filterSpec{
				{"image-id", []string{imageId2}},
				{"group-name", []string{group1.Name}},
			},
		},
	}
	for i, t := range tests {
		c.Logf("%d. %s", i, t.about)
		var f *ec2.Filter
		if t.filters != nil {
			f = ec2.NewFilter()
			for _, spec := range t.filters {
				f.Add(spec.name, spec.values...)
			}
		}
		resp, err := s.ec2.Instances(t.instanceIds, f)
		if t.err != "" {
			c.Check(err, ErrorMatches, t.err)
			continue
		}
		c.Assert(err, IsNil)
		insts := make(map[string]*ec2.Instance)
		for _, r := range resp.Reservations {
			for j := range r.Instances {
				inst := &r.Instances[j]
				c.Check(insts[inst.InstanceId], IsNil, Commentf("duplicate instance id: %q", inst.InstanceId))
				insts[inst.InstanceId] = inst
			}
		}
		if !t.allowExtra {
			c.Check(insts, HasLen, len(t.resultIds), Commentf("expected %d instances got %#v", len(t.resultIds), insts))
		}
		for j, id := range t.resultIds {
			c.Check(insts[id], NotNil, Commentf("instance id %d (%q) not found; got %#v", j, id, insts))
		}
	}
}
Exemple #16
0
func (s *ServerTests) TestIPPerms(c *C) {
	g0 := s.makeTestGroup(c, "goamz-test0", "ec2test group 0")
	defer s.ec2.DeleteSecurityGroup(g0)

	g1 := s.makeTestGroup(c, "goamz-test1", "ec2test group 1")
	defer s.ec2.DeleteSecurityGroup(g1)

	resp, err := s.ec2.SecurityGroups([]ec2.SecurityGroup{g0, g1}, nil)
	c.Assert(err, IsNil)
	c.Assert(resp.Groups, HasLen, 2)
	c.Assert(resp.Groups[0].IPPerms, HasLen, 0)
	c.Assert(resp.Groups[1].IPPerms, HasLen, 0)

	ownerId := resp.Groups[0].OwnerId

	// test some invalid parameters
	// TODO more
	_, err = s.ec2.AuthorizeSecurityGroup(g0, []ec2.IPPerm{{
		Protocol:  "tcp",
		FromPort:  0,
		ToPort:    1024,
		SourceIPs: []string{"z127.0.0.1/24"},
	}})
	c.Assert(err, NotNil)
	c.Check(err.(*ec2.Error).Code, Equals, "InvalidPermission.Malformed")

	// Check that AuthorizeSecurityGroup adds the correct authorizations.
	_, err = s.ec2.AuthorizeSecurityGroup(g0, []ec2.IPPerm{{
		Protocol:  "tcp",
		FromPort:  2000,
		ToPort:    2001,
		SourceIPs: []string{"127.0.0.0/24"},
		SourceGroups: []ec2.UserSecurityGroup{{
			Name: g1.Name,
		}, {
			Id: g0.Id,
		}},
	}, {
		Protocol:  "tcp",
		FromPort:  2000,
		ToPort:    2001,
		SourceIPs: []string{"200.1.1.34/32"},
	}})
	c.Assert(err, IsNil)

	resp, err = s.ec2.SecurityGroups([]ec2.SecurityGroup{g0}, nil)
	c.Assert(err, IsNil)
	c.Assert(resp.Groups, HasLen, 1)
	c.Assert(resp.Groups[0].IPPerms, HasLen, 1)

	perm := resp.Groups[0].IPPerms[0]
	srcg := perm.SourceGroups
	c.Assert(srcg, HasLen, 2)

	// Normalize so we don't care about returned order.
	if srcg[0].Name == g1.Name {
		srcg[0], srcg[1] = srcg[1], srcg[0]
	}
	c.Check(srcg[0].Name, Equals, g0.Name)
	c.Check(srcg[0].Id, Equals, g0.Id)
	c.Check(srcg[0].OwnerId, Equals, ownerId)
	c.Check(srcg[1].Name, Equals, g1.Name)
	c.Check(srcg[1].Id, Equals, g1.Id)
	c.Check(srcg[1].OwnerId, Equals, ownerId)

	sort.Strings(perm.SourceIPs)
	c.Check(perm.SourceIPs, DeepEquals, []string{"127.0.0.0/24", "200.1.1.34/32"})

	// Check that we can't delete g1 (because g0 is using it)
	_, err = s.ec2.DeleteSecurityGroup(g1)
	c.Assert(err, NotNil)
	c.Check(err.(*ec2.Error).Code, Equals, "InvalidGroup.InUse")

	_, err = s.ec2.RevokeSecurityGroup(g0, []ec2.IPPerm{{
		Protocol:     "tcp",
		FromPort:     2000,
		ToPort:       2001,
		SourceGroups: []ec2.UserSecurityGroup{{Id: g1.Id}},
	}, {
		Protocol:  "tcp",
		FromPort:  2000,
		ToPort:    2001,
		SourceIPs: []string{"200.1.1.34/32"},
	}})
	c.Assert(err, IsNil)

	resp, err = s.ec2.SecurityGroups([]ec2.SecurityGroup{g0}, nil)
	c.Assert(err, IsNil)
	c.Assert(resp.Groups, HasLen, 1)
	c.Assert(resp.Groups[0].IPPerms, HasLen, 1)

	perm = resp.Groups[0].IPPerms[0]
	srcg = perm.SourceGroups
	c.Assert(srcg, HasLen, 1)
	c.Check(srcg[0].Name, Equals, g0.Name)
	c.Check(srcg[0].Id, Equals, g0.Id)
	c.Check(srcg[0].OwnerId, Equals, ownerId)

	c.Check(perm.SourceIPs, DeepEquals, []string{"127.0.0.0/24"})

	// We should be able to delete g1 now because we've removed its only use.
	_, err = s.ec2.DeleteSecurityGroup(g1)
	c.Assert(err, IsNil)

	_, err = s.ec2.DeleteSecurityGroup(g0)
	c.Assert(err, IsNil)

	f := ec2.NewFilter()
	f.Add("group-id", g0.Id, g1.Id)
	resp, err = s.ec2.SecurityGroups(nil, f)
	c.Assert(err, IsNil)
	c.Assert(resp.Groups, HasLen, 0)
}
Exemple #17
0
func (s *StepCreateVolume) Run(state multistep.StateBag) multistep.StepAction {
	ec2conn := state.Get("ec2").(ec2.EC2)
	image := state.Get("source_image").(*ec2.Image)
	instance := state.Get("instance").(*ec2.Instance)
	ui := state.Get("ui").(packer.Ui)

	// Determine the root device snapshot
	log.Printf("Searching for root device of the image (%s)", image.RootDeviceName)
	var rootDevice *ec2.BlockDeviceMapping
	for _, device := range image.BlockDevices {
		if device.DeviceName == image.RootDeviceName {
			rootDevice = &device
			break
		}
	}

	if rootDevice == nil {
		err := fmt.Errorf("Couldn't find root device!")
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	ui.Say("Creating the root volume...")
	createVolume := &ec2.CreateVolume{
		AvailZone:  instance.AvailZone,
		Size:       rootDevice.VolumeSize,
		SnapshotId: rootDevice.SnapshotId,
		VolumeType: rootDevice.VolumeType,
		IOPS:       rootDevice.IOPS,
	}
	log.Printf("Create args: %#v", createVolume)

	createVolumeResp, err := ec2conn.CreateVolume(createVolume)
	if err != nil {
		err := fmt.Errorf("Error creating root volume: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	// Set the volume ID so we remember to delete it later
	s.volumeId = createVolumeResp.VolumeId
	log.Printf("Volume ID: %s", s.volumeId)

	// Wait for the volume to become ready
	stateChange := awscommon.StateChangeConf{
		Conn:      ec2conn,
		Pending:   []string{"creating"},
		StepState: state,
		Target:    "available",
		Refresh: func() (interface{}, string, error) {
			resp, err := ec2conn.Volumes([]string{s.volumeId}, ec2.NewFilter())
			if err != nil {
				return nil, "", err
			}

			v := resp.Volumes[0]
			return v, v.Status, nil
		},
	}

	_, err = awscommon.WaitForState(&stateChange)
	if err != nil {
		err := fmt.Errorf("Error waiting for volume: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	state.Put("volume_id", s.volumeId)
	return multistep.ActionContinue
}
func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepAction {
	ec2conn := state.Get("ec2").(ec2.EC2)
	keyName := state.Get("keyPair").(string)
	securityGroupId := state.Get("securityGroupId").(string)
	ui := state.Get("ui").(packer.Ui)

	userData := s.UserData
	if s.UserDataFile != "" {
		contents, err := ioutil.ReadFile(s.UserDataFile)
		if err != nil {
			state.Put("error", fmt.Errorf("Problem reading user data file: %s", err))
			return multistep.ActionHalt
		}

		userData = string(contents)
	}

	runOpts := &ec2.RunInstances{
		KeyName:            keyName,
		ImageId:            s.SourceAMI,
		InstanceType:       s.InstanceType,
		UserData:           []byte(userData),
		MinCount:           0,
		MaxCount:           0,
		SecurityGroups:     []ec2.SecurityGroup{ec2.SecurityGroup{Id: securityGroupId}},
		IamInstanceProfile: s.IamInstanceProfile,
		SubnetId:           s.SubnetId,
		BlockDevices:       s.BlockDevices.BuildLaunchDevices(),
	}

	ui.Say("Launching a source AWS instance...")
	imageResp, err := ec2conn.Images([]string{s.SourceAMI}, ec2.NewFilter())
	if err != nil {
		state.Put("error", fmt.Errorf("There was a problem with the source AMI: %s", err))
		return multistep.ActionHalt
	}

	if len(imageResp.Images) != 1 {
		state.Put("error", fmt.Errorf("The source AMI '%s' could not be found.", s.SourceAMI))
		return multistep.ActionHalt
	}

	if s.ExpectedRootDevice != "" && imageResp.Images[0].RootDeviceType != s.ExpectedRootDevice {
		state.Put("error", fmt.Errorf(
			"The provided source AMI has an invalid root device type.\n"+
				"Expected '%s', got '%s'.",
			s.ExpectedRootDevice, imageResp.Images[0].RootDeviceType))
		return multistep.ActionHalt
	}

	runResp, err := ec2conn.RunInstances(runOpts)
	if err != nil {
		err := fmt.Errorf("Error launching source instance: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	s.instance = &runResp.Instances[0]
	log.Printf("instance id: %s", s.instance.InstanceId)

	ui.Say(fmt.Sprintf("Waiting for instance (%s) to become ready...", s.instance.InstanceId))
	stateChange := StateChangeConf{
		Conn:      ec2conn,
		Pending:   []string{"pending"},
		Target:    "running",
		Refresh:   InstanceStateRefreshFunc(ec2conn, s.instance),
		StepState: state,
	}
	latestInstance, err := WaitForState(&stateChange)
	if err != nil {
		err := fmt.Errorf("Error waiting for instance (%s) to become ready: %s", s.instance.InstanceId, err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	s.instance = latestInstance.(*ec2.Instance)

	if s.Debug {
		if s.instance.DNSName != "" {
			ui.Message(fmt.Sprintf("Public DNS: %s", s.instance.DNSName))
		}

		if s.instance.PrivateIpAddress != "" {
			ui.Message(fmt.Sprintf("Private IP: %s", s.instance.PrivateIpAddress))
		}
	}

	state.Put("instance", s.instance)

	return multistep.ActionContinue
}