// Security group import fans out to multiple resources due to the
// security group rules. Instead of creating one resource with nested
// rules, we use the best practices approach of one resource per rule.
func resourceAwsSecurityGroupImportState(
	d *schema.ResourceData,
	meta interface{}) ([]*schema.ResourceData, error) {
	conn := meta.(*AWSClient).ec2conn

	// First query the security group
	sgRaw, _, err := SGStateRefreshFunc(conn, d.Id())()
	if err != nil {
		return nil, err
	}
	if sgRaw == nil {
		return nil, fmt.Errorf("security group not found")
	}
	sg := sgRaw.(*ec2.SecurityGroup)
	sgId := d.Id()

	// Start building our results
	results := make([]*schema.ResourceData, 1,
		1+len(sg.IpPermissions)+len(sg.IpPermissionsEgress))
	results[0] = d

	// Construct the rules
	ruleResource := resourceAwsSecurityGroupRule()
	permMap := map[string][]*ec2.IpPermission{
		"ingress": sg.IpPermissions,
		"egress":  sg.IpPermissionsEgress,
	}
	for ruleType, perms := range permMap {
		for _, perm := range perms {
			// Construct the rule. We do this by populating the absolute
			// minimum necessary for Refresh on the rule to work. This
			// happens to be a lot of fields since they're almost all needed
			// for de-dupping.
			id := ipPermissionIDHash(sgId, ruleType, perm)
			d := ruleResource.Data(nil)
			d.SetId(id)
			d.SetType("aws_security_group_rule")
			d.Set("security_group_id", sgId)
			d.Set("type", ruleType)
			// XXX If the rule contained more than one source security group, this
			// will choose one of them. We actually need to create one rule for each
			// source security group.
			setFromIPPerm(d, sg, perm)
			results = append(results, d)
		}
	}

	return results, nil
}
// Route table import also imports all the rules
func resourceAwsRouteTableImportState(
	d *schema.ResourceData,
	meta interface{}) ([]*schema.ResourceData, error) {
	conn := meta.(*AWSClient).ec2conn

	// First query the resource itself
	id := d.Id()
	resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesInput{
		RouteTableIds: []*string{&id},
	})
	if err != nil {
		return nil, err
	}
	if len(resp.RouteTables) < 1 || resp.RouteTables[0] == nil {
		return nil, fmt.Errorf("route table %s is not found", id)
	}
	table := resp.RouteTables[0]

	// Start building our results
	results := make([]*schema.ResourceData, 1,
		2+len(table.Associations)+len(table.Routes))
	results[0] = d

	{
		// Construct the routes
		subResource := resourceAwsRoute()
		for _, route := range table.Routes {
			// Ignore the local/default route
			if route.GatewayId != nil && *route.GatewayId == "local" {
				continue
			}

			// Minimal data for route
			d := subResource.Data(nil)
			d.SetType("aws_route")
			d.Set("route_table_id", id)
			d.Set("destination_cidr_block", route.DestinationCidrBlock)
			d.SetId(routeIDHash(d, route))
			results = append(results, d)
		}
	}

	{
		// Construct the associations
		subResource := resourceAwsRouteTableAssociation()
		for _, assoc := range table.Associations {
			if *assoc.Main {
				// Ignore
				continue
			}

			// Minimal data for route
			d := subResource.Data(nil)
			d.SetType("aws_route_table_association")
			d.Set("route_table_id", assoc.RouteTableId)
			d.SetId(*assoc.RouteTableAssociationId)
			results = append(results, d)
		}
	}

	{
		// Construct the main associations. We could do this above but
		// I keep this as a separate section since it is a separate resource.
		subResource := resourceAwsMainRouteTableAssociation()
		for _, assoc := range table.Associations {
			if !*assoc.Main {
				// Ignore
				continue
			}

			// Minimal data for route
			d := subResource.Data(nil)
			d.SetType("aws_main_route_table_association")
			d.Set("route_table_id", id)
			d.Set("vpc_id", table.VpcId)
			d.SetId(*assoc.RouteTableAssociationId)
			results = append(results, d)
		}
	}

	return results, nil
}
// Security group import fans out to multiple resources due to the
// security group rules. Instead of creating one resource with nested
// rules, we use the best practices approach of one resource per rule.
func resourceAwsSecurityGroupImportState(
	d *schema.ResourceData,
	meta interface{}) ([]*schema.ResourceData, error) {
	conn := meta.(*AWSClient).ec2conn

	// First query the security group
	sgRaw, _, err := SGStateRefreshFunc(conn, d.Id())()
	if err != nil {
		return nil, err
	}
	if sgRaw == nil {
		return nil, fmt.Errorf("security group not found")
	}
	sg := sgRaw.(*ec2.SecurityGroup)
	sgId := d.Id()

	// Start building our results
	results := make([]*schema.ResourceData, 1,
		1+len(sg.IpPermissions)+len(sg.IpPermissionsEgress))
	results[0] = d

	// Construct the rules
	ruleResource := resourceAwsSecurityGroupRule()
	permMap := map[string][]*ec2.IpPermission{
		"ingress": sg.IpPermissions,
		"egress":  sg.IpPermissionsEgress,
	}
	for ruleType, perms := range permMap {
		for _, perm := range perms {
			// Construct the rule. We do this by populating the absolute
			// minimum necessary for Refresh on the rule to work. This
			// happens to be a lot of fields since they're almost all needed
			// for de-dupping.
			id := ipPermissionIDHash(sgId, ruleType, perm)
			d := ruleResource.Data(nil)
			d.SetId(id)
			d.SetType("aws_security_group_rule")
			d.Set("security_group_id", sgId)
			d.Set("type", ruleType)

			// 'self' is false by default. Below, we range over the group ids and set true
			// if the parent sg id is found
			d.Set("self", false)

			if len(perm.UserIdGroupPairs) > 0 {
				s := perm.UserIdGroupPairs[0]

				// Check for Pair that is the same as the Security Group, to denote self.
				// Otherwise, mark the group id in source_security_group_id
				isVPC := sg.VpcId != nil && *sg.VpcId != ""
				if isVPC {
					if *s.GroupId == *sg.GroupId {
						d.Set("self", true)
						// prune the self reference from the UserIdGroupPairs, so we don't
						// have duplicate sg ids (both self and in source_security_group_id)
						perm.UserIdGroupPairs = append(perm.UserIdGroupPairs[:0], perm.UserIdGroupPairs[0+1:]...)
					}
				} else {
					if *s.GroupName == *sg.GroupName {
						d.Set("self", true)
						// prune the self reference from the UserIdGroupPairs, so we don't
						// have duplicate sg ids (both self and in source_security_group_id)
						perm.UserIdGroupPairs = append(perm.UserIdGroupPairs[:0], perm.UserIdGroupPairs[0+1:]...)
					}
				}
			}

			// XXX If the rule contained more than one source security group, this
			// will choose one of them. We actually need to create one rule for each
			// source security group.
			if err := setFromIPPerm(d, sg, perm); err != nil {
				return nil, errwrap.Wrapf("Error importing AWS Security Group: {{err}}", err)
			}
			results = append(results, d)
		}
	}

	return results, nil
}