Example #1
0
func (e *SecurityGroup) Find(c *fi.Context) (*SecurityGroup, error) {
	cloud := c.Cloud.(*awsup.AWSCloud)

	var vpcID *string
	if e.VPC != nil {
		vpcID = e.VPC.ID
	}

	if vpcID == nil || e.Name == nil {
		return nil, nil
	}

	filters := cloud.BuildFilters(e.Name)
	filters = append(filters, awsup.NewEC2Filter("vpc-id", *vpcID))
	filters = append(filters, awsup.NewEC2Filter("group-name", *e.Name))

	request := &ec2.DescribeSecurityGroupsInput{
		Filters: filters,
	}

	response, err := cloud.EC2.DescribeSecurityGroups(request)
	if err != nil {
		return nil, fmt.Errorf("error listing SecurityGroups: %v", err)
	}
	if response == nil || len(response.SecurityGroups) == 0 {
		return nil, nil
	}

	if len(response.SecurityGroups) != 1 {
		return nil, fmt.Errorf("found multiple SecurityGroups matching tags")
	}
	sg := response.SecurityGroups[0]
	actual := &SecurityGroup{
		ID:          sg.GroupId,
		Name:        sg.GroupName,
		Description: sg.Description,
		VPC:         &VPC{ID: sg.VpcId},
	}

	glog.V(2).Infof("found matching SecurityGroup %q", *actual.ID)
	e.ID = actual.ID

	return actual, nil
}
Example #2
0
func buildEC2Filters(cloud fi.Cloud) []*ec2.Filter {
	awsCloud := cloud.(*awsup.AWSCloud)
	tags := awsCloud.Tags()

	var filters []*ec2.Filter
	for k, v := range tags {
		filter := awsup.NewEC2Filter("tag:"+k, v)
		filters = append(filters, filter)
	}
	return filters
}
Example #3
0
func (e *InternetGateway) Find(c *fi.Context) (*InternetGateway, error) {
	cloud := c.Cloud.(*awsup.AWSCloud)

	request := &ec2.DescribeInternetGatewaysInput{}

	shared := fi.BoolValue(e.Shared)
	if shared {
		if fi.StringValue(e.VPC.ID) == "" {
			return nil, fmt.Errorf("VPC ID is required when InternetGateway is shared")
		}

		request.Filters = []*ec2.Filter{awsup.NewEC2Filter("attachment.vpc-id", *e.VPC.ID)}
	} else {
		if e.ID != nil {
			request.InternetGatewayIds = []*string{e.ID}
		} else {
			request.Filters = cloud.BuildFilters(e.Name)
		}
	}

	response, err := cloud.EC2.DescribeInternetGateways(request)
	if err != nil {
		return nil, fmt.Errorf("error listing InternetGateways: %v", err)
	}
	if response == nil || len(response.InternetGateways) == 0 {
		return nil, nil
	}

	if len(response.InternetGateways) != 1 {
		return nil, fmt.Errorf("found multiple InternetGateways matching tags")
	}
	igw := response.InternetGateways[0]
	actual := &InternetGateway{
		ID:   igw.InternetGatewayId,
		Name: findNameTag(igw.Tags),
	}

	glog.V(2).Infof("found matching InternetGateway %q", *actual.ID)

	for _, attachment := range igw.Attachments {
		actual.VPC = &VPC{ID: attachment.VpcId}
	}

	// Prevent spurious comparison failures
	actual.Shared = e.Shared
	if e.ID == nil {
		e.ID = actual.ID
	}

	return actual, nil
}
Example #4
0
func (e *SecurityGroupRule) Find(c *fi.Context) (*SecurityGroupRule, error) {
	cloud := c.Cloud.(*awsup.AWSCloud)

	if e.SecurityGroup == nil || e.SecurityGroup.ID == nil {
		return nil, nil
	}

	request := &ec2.DescribeSecurityGroupsInput{
		Filters: []*ec2.Filter{
			awsup.NewEC2Filter("group-id", *e.SecurityGroup.ID),
		},
	}

	response, err := cloud.EC2.DescribeSecurityGroups(request)
	if err != nil {
		return nil, fmt.Errorf("error listing SecurityGroup: %v", err)
	}

	if response == nil || len(response.SecurityGroups) == 0 {
		return nil, nil
	}

	if len(response.SecurityGroups) != 1 {
		glog.Fatalf("found multiple security groups for id=%s", *e.SecurityGroup.ID)
	}
	sg := response.SecurityGroups[0]
	//glog.V(2).Info("found existing security group")

	var foundRule *ec2.IpPermission

	matchProtocol := "-1" // Wildcard
	if e.Protocol != nil {
		matchProtocol = *e.Protocol
	}

	ipPermissions := sg.IpPermissions
	if fi.BoolValue(e.Egress) {
		ipPermissions = sg.IpPermissionsEgress
	}

	for _, rule := range ipPermissions {
		if aws.Int64Value(rule.FromPort) != aws.Int64Value(e.FromPort) {
			continue
		}
		if aws.Int64Value(rule.ToPort) != aws.Int64Value(e.ToPort) {
			continue
		}
		if aws.StringValue(rule.IpProtocol) != matchProtocol {
			continue
		}
		if e.CIDR != nil {
			// TODO: Only if len 1?
			match := false
			for _, ipRange := range rule.IpRanges {
				if aws.StringValue(ipRange.CidrIp) == *e.CIDR {
					match = true
					break
				}
			}
			if !match {
				continue
			}
		}

		if e.SourceGroup != nil {
			// TODO: Only if len 1?
			match := false
			for _, spec := range rule.UserIdGroupPairs {
				if aws.StringValue(spec.GroupId) == *e.SourceGroup.ID {
					match = true
					break
				}
			}
			if !match {
				continue
			}
		}
		foundRule = rule
		break
	}

	if foundRule != nil {
		actual := &SecurityGroupRule{
			Name:          e.Name,
			SecurityGroup: &SecurityGroup{ID: e.SecurityGroup.ID},
			FromPort:      foundRule.FromPort,
			ToPort:        foundRule.ToPort,
			Protocol:      foundRule.IpProtocol,
			Egress:        e.Egress,
		}

		if aws.StringValue(actual.Protocol) == "-1" {
			actual.Protocol = nil
		}
		if e.CIDR != nil {
			actual.CIDR = e.CIDR
		}
		if e.SourceGroup != nil {
			actual.SourceGroup = &SecurityGroup{ID: e.SourceGroup.ID}
		}
		return actual, nil
	}

	return nil, nil
}
Example #5
0
func (e *Instance) Find(c *fi.Context) (*Instance, error) {
	cloud := c.Cloud.(*awsup.AWSCloud)

	filters := cloud.BuildFilters(e.Name)
	filters = append(filters, awsup.NewEC2Filter("instance-state-name", "pending", "running", "stopping", "stopped"))
	request := &ec2.DescribeInstancesInput{
		Filters: filters,
	}

	response, err := cloud.EC2.DescribeInstances(request)
	if err != nil {
		return nil, fmt.Errorf("error listing instances: %v", err)
	}

	instances := []*ec2.Instance{}
	if response != nil {
		for _, reservation := range response.Reservations {
			for _, instance := range reservation.Instances {
				instances = append(instances, instance)
			}
		}
	}

	if len(instances) == 0 {
		return nil, nil
	}

	if len(instances) != 1 {
		return nil, fmt.Errorf("found multiple Instances with name: %s", *e.Name)
	}

	glog.V(2).Info("found existing instance")
	i := instances[0]

	if i.InstanceId == nil {
		return nil, fmt.Errorf("found instance, but InstanceId was nil")
	}

	actual := &Instance{
		ID:               i.InstanceId,
		PrivateIPAddress: i.PrivateIpAddress,
		InstanceType:     i.InstanceType,
		ImageID:          i.ImageId,
		Name:             findNameTag(i.Tags),
	}

	// Fetch instance UserData
	{
		request := &ec2.DescribeInstanceAttributeInput{}
		request.InstanceId = i.InstanceId
		request.Attribute = aws.String("userData")
		response, err := cloud.EC2.DescribeInstanceAttribute(request)
		if err != nil {
			return nil, fmt.Errorf("error querying EC2 for user metadata for instance %q: %v", *i.InstanceId)
		}
		if response.UserData != nil {
			b, err := base64.StdEncoding.DecodeString(aws.StringValue(response.UserData.Value))
			if err != nil {
				return nil, fmt.Errorf("error decoding EC2 UserData: %v", err)
			}
			actual.UserData = fi.NewBytesResource(b)
		}
	}

	if i.SubnetId != nil {
		actual.Subnet = &Subnet{ID: i.SubnetId}
	}
	if i.KeyName != nil {
		actual.SSHKey = &SSHKey{Name: i.KeyName}
	}

	for _, sg := range i.SecurityGroups {
		actual.SecurityGroups = append(actual.SecurityGroups, &SecurityGroup{ID: sg.GroupId})
	}

	associatePublicIpAddress := false
	for _, ni := range i.NetworkInterfaces {
		if aws.StringValue(ni.Association.PublicIp) != "" {
			associatePublicIpAddress = true
		}
	}
	actual.AssociatePublicIP = &associatePublicIpAddress

	if i.IamInstanceProfile != nil {
		actual.IAMInstanceProfile = &IAMInstanceProfile{Name: nameFromIAMARN(i.IamInstanceProfile.Arn)}
	}

	actual.Tags = mapEC2TagsToMap(i.Tags)

	e.ID = actual.ID

	// Avoid spurious changes on ImageId
	if e.ImageID != nil && actual.ImageID != nil && *actual.ImageID != *e.ImageID {
		image, err := cloud.ResolveImage(*e.ImageID)
		if err != nil {
			glog.Warningf("unable to resolve image: %q: %v", *e.ImageID, err)
		} else if image == nil {
			glog.Warningf("unable to resolve image: %q: not found", *e.ImageID)
		} else if aws.StringValue(image.ImageId) == *actual.ImageID {
			glog.V(4).Infof("Returning matching ImageId as expected name: %q -> %q", *actual.ImageID, *e.ImageID)
			actual.ImageID = e.ImageID
		}
	}

	return actual, nil
}
Example #6
0
func (e *ElasticIP) find(cloud *awsup.AWSCloud) (*ElasticIP, error) {
	publicIP := e.PublicIP
	allocationID := e.ID

	tagOnResourceID, err := e.findTagOnResourceID(cloud)
	if err != nil {
		return nil, err
	}
	// Find via tag on foreign resource
	if allocationID == nil && publicIP == nil && e.TagUsingKey != nil && tagOnResourceID != nil {
		var filters []*ec2.Filter
		filters = append(filters, awsup.NewEC2Filter("key", *e.TagUsingKey))
		filters = append(filters, awsup.NewEC2Filter("resource-id", *tagOnResourceID))

		request := &ec2.DescribeTagsInput{
			Filters: filters,
		}

		response, err := cloud.EC2.DescribeTags(request)
		if err != nil {
			return nil, fmt.Errorf("error listing tags: %v", err)
		}

		if response == nil || len(response.Tags) == 0 {
			return nil, nil
		}

		if len(response.Tags) != 1 {
			return nil, fmt.Errorf("found multiple tags for: %v", e)
		}
		t := response.Tags[0]
		publicIP = t.Value
		glog.V(2).Infof("Found public IP via tag: %v", *publicIP)
	}

	if publicIP != nil || allocationID != nil {
		request := &ec2.DescribeAddressesInput{}
		if allocationID != nil {
			request.AllocationIds = []*string{allocationID}
		} else if publicIP != nil {
			request.Filters = []*ec2.Filter{awsup.NewEC2Filter("public-ip", *publicIP)}
		}

		response, err := cloud.EC2.DescribeAddresses(request)
		if err != nil {
			return nil, fmt.Errorf("error listing ElasticIPs: %v", err)
		}

		if response == nil || len(response.Addresses) == 0 {
			return nil, nil
		}

		if len(response.Addresses) != 1 {
			return nil, fmt.Errorf("found multiple ElasticIPs for: %v", e)
		}
		a := response.Addresses[0]
		actual := &ElasticIP{
			ID:       a.AllocationId,
			PublicIP: a.PublicIp,
		}

		// These two are weird properties; we copy them so they don't come up as changes
		actual.TagUsingKey = e.TagUsingKey
		actual.TagOnResource = e.TagOnResource

		e.ID = actual.ID

		return actual, nil
	}

	return nil, nil
}