func resource_aws_instance_update_state(
	s *terraform.ResourceState,
	instance *ec2.Instance) (*terraform.ResourceState, error) {
	s.Attributes["availability_zone"] = instance.AvailZone
	s.Attributes["key_name"] = instance.KeyName
	s.Attributes["public_dns"] = instance.DNSName
	s.Attributes["public_ip"] = instance.PublicIpAddress
	s.Attributes["private_dns"] = instance.PrivateDNSName
	s.Attributes["private_ip"] = instance.PrivateIpAddress
	s.Attributes["subnet_id"] = instance.SubnetId
	s.Dependencies = nil

	// Extract the existing security groups
	useID := false
	if raw := flatmap.Expand(s.Attributes, "security_groups"); raw != nil {
		if sgs, ok := raw.([]interface{}); ok {
			for _, sg := range sgs {
				str, ok := sg.(string)
				if !ok {
					continue
				}

				if strings.HasPrefix(str, "sg-") {
					useID = true
					break
				}
			}
		}
	}

	// Build up the security groups
	sgs := make([]string, len(instance.SecurityGroups))
	for i, sg := range instance.SecurityGroups {
		if instance.SubnetId != "" && useID {
			sgs[i] = sg.Id
		} else {
			sgs[i] = sg.Name
		}

		s.Dependencies = append(s.Dependencies,
			terraform.ResourceDependency{ID: sg.Id},
		)
	}
	flatmap.Map(s.Attributes).Merge(flatmap.Flatten(map[string]interface{}{
		"security_groups": sgs,
	}))

	if instance.SubnetId != "" {
		s.Dependencies = append(s.Dependencies,
			terraform.ResourceDependency{ID: instance.SubnetId},
		)
	}

	return s, nil
}
func resource_aws_route_table_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Our resulting state
	rs := s.MergeDiff(d)

	// Get our routes out of the merge
	oldroutes := flatmap.Expand(s.Attributes, "route")
	routes := flatmap.Expand(s.MergeDiff(d).Attributes, "route")

	// Determine the route operations we need to perform
	ops := routeTableOps(oldroutes, routes)
	if len(ops) == 0 {
		return s, nil
	}

	// Go through each operation, performing each one at a time.
	// We store the updated state on each operation so that if any
	// individual operation fails, we can return a valid partial state.
	var err error
	resultRoutes := make([]map[string]string, 0, len(ops))
	for _, op := range ops {
		switch op.Op {
		case routeTableOpCreate:
			opts := ec2.CreateRoute{
				RouteTableId:         s.ID,
				DestinationCidrBlock: op.Route.DestinationCidrBlock,
				GatewayId:            op.Route.GatewayId,
				InstanceId:           op.Route.InstanceId,
			}

			_, err = ec2conn.CreateRoute(&opts)
		case routeTableOpReplace:
			opts := ec2.ReplaceRoute{
				RouteTableId:         s.ID,
				DestinationCidrBlock: op.Route.DestinationCidrBlock,
				GatewayId:            op.Route.GatewayId,
				InstanceId:           op.Route.InstanceId,
			}

			_, err = ec2conn.ReplaceRoute(&opts)
		case routeTableOpDelete:
			_, err = ec2conn.DeleteRoute(
				s.ID, op.Route.DestinationCidrBlock)
		}

		if err != nil {
			// Exit early so we can return what we've done so far
			break
		}

		// If we didn't delete the route, append it to the list of routes
		// we have.
		if op.Op != routeTableOpDelete {
			resultMap := map[string]string{"cidr_block": op.Route.DestinationCidrBlock}
			if op.Route.GatewayId != "" {
				resultMap["gateway_id"] = op.Route.GatewayId
			} else if op.Route.InstanceId != "" {
				resultMap["instance_id"] = op.Route.InstanceId
			}

			resultRoutes = append(resultRoutes, resultMap)
		}
	}

	// Update our state with the settings
	flatmap.Map(rs.Attributes).Merge(flatmap.Flatten(map[string]interface{}{
		"route": resultRoutes,
	}))

	return rs, err
}