func NewLegacyResourceAddress(addr addrs.AbsResource) *ResourceAddress {
	ret := &ResourceAddress{
		Type: addr.Resource.Type,
		Name: addr.Resource.Name,
	}
	switch addr.Resource.Mode {
	case addrs.ManagedResourceMode:
		ret.Mode = config.ManagedResourceMode
	case addrs.DataResourceMode:
		ret.Mode = config.DataResourceMode
	default:
		panic(fmt.Errorf("cannot shim %s to legacy config.ResourceMode value", addr.Resource.Mode))
	}
	path := make([]string, len(addr.Module))
	for i, step := range addr.Module {
		if step.InstanceKey != addrs.NoKey {
			panic(fmt.Errorf("cannot shim module instance step with key %#v to legacy ResourceAddress.Path", step.InstanceKey))
		}
		path[i] = step.Name
	}
	ret.Path = path
	ret.Index = -1
	return ret
}
NewLegacyResourceAddress creates a ResourceAddress from a new-style
addrs.AbsResource value.

This is provided for shimming purposes so that we can still easily call into
older functions that expect the ResourceAddress type.
package terraform
import (
	"fmt"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"github.com/hashicorp/terraform/addrs"
	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/configs"
)
type ResourceAddress struct {
	Path []string
	Index int
	InstanceType    InstanceType
	InstanceTypeSet bool
	Name            string
	Type            string
	Mode            config.ResourceMode  
}
func (r *ResourceAddress) Copy() *ResourceAddress {
	if r == nil {
		return nil
	}
	n := &ResourceAddress{
		Path:         make([]string, 0, len(r.Path)),
		Index:        r.Index,
		InstanceType: r.InstanceType,
		Name:         r.Name,
		Type:         r.Type,
		Mode:         r.Mode,
	}
	n.Path = append(n.Path, r.Path...)
	return n
}
func (r *ResourceAddress) String() string {
	var result []string
	for _, p := range r.Path {
		result = append(result, "module", p)
	}
	switch r.Mode {
	case config.ManagedResourceMode:
	case config.DataResourceMode:
		result = append(result, "data")
	default:
		panic(fmt.Errorf("unsupported resource mode %s", r.Mode))
	}
	if r.Type != "" {
		result = append(result, r.Type)
	}
	if r.Name != "" {
		name := r.Name
		if r.InstanceTypeSet {
			switch r.InstanceType {
			case TypePrimary:
				name += ".primary"
			case TypeDeposed:
				name += ".deposed"
			case TypeTainted:
				name += ".tainted"
			}
		}
		if r.Index >= 0 {
			name += fmt.Sprintf("[%d]", r.Index)
		}
		result = append(result, name)
	}
	return strings.Join(result, ".")
}
func (r *ResourceAddress) HasResourceSpec() bool {
	return r.Type != "" && r.Name != ""
}
func (r *ResourceAddress) WholeModuleAddress() *ResourceAddress {
	return &ResourceAddress{
		Path:            r.Path,
		Index:           -1,
		InstanceTypeSet: false,
	}
}
func (r *ResourceAddress) MatchesResourceConfig(path addrs.Module, rc *configs.Resource) bool {
	if r.HasResourceSpec() {
		switch r.Mode {
		case config.ManagedResourceMode:
			if rc.Mode != addrs.ManagedResourceMode {
				return false
			}
		case config.DataResourceMode:
			if rc.Mode != addrs.DataResourceMode {
				return false
			}
		}
		if r.Type != rc.Type || r.Name != rc.Name {
			return false
		}
	}
	addrPath := r.Path
	if len(addrPath) == 0 {
		addrPath = nil
	}
	if len(path) == 0 {
		path = nil
	}
	rawPath := []string(path)
	return reflect.DeepEqual(addrPath, rawPath)
}
func (r *ResourceAddress) stateId() string {
	result := fmt.Sprintf("%s.%s", r.Type, r.Name)
	switch r.Mode {
	case config.ManagedResourceMode:
	case config.DataResourceMode:
		result = fmt.Sprintf("data.%s", result)
	default:
		panic(fmt.Errorf("unknown resource mode: %s", r.Mode))
	}
	if r.Index >= 0 {
		result += fmt.Sprintf(".%d", r.Index)
	}
	return result
}
func parseResourceAddressConfig(r *config.Resource) (*ResourceAddress, error) {
	return &ResourceAddress{
		Type:         r.Type,
		Name:         r.Name,
		Index:        -1,
		InstanceType: TypePrimary,
		Mode:         r.Mode,
	}, nil
}
func parseResourceAddressInternal(s string) (*ResourceAddress, error) {
	parts := strings.Split(s, ".")
	if len(parts) < 2 || len(parts) > 4 {
		return nil, fmt.Errorf("Invalid internal resource address format: %s", s)
	}
	mode := config.ManagedResourceMode
	if len(parts) > 2 && parts[0] == "data" {
		mode = config.DataResourceMode
		parts = parts[1:]
	}
	if len(parts) > 3 && mode != config.DataResourceMode {
		return nil, fmt.Errorf("Invalid internal resource address format: %s", s)
	}
	addr := &ResourceAddress{
		Type:         parts[0],
		Name:         parts[1],
		Index:        -1,
		InstanceType: TypePrimary,
		Mode:         mode,
	}
	if len(parts) > 2 {
		idx, err := strconv.ParseInt(parts[2], 0, 0)
		if err != nil {
			return nil, fmt.Errorf("Error parsing resource address %q: %s", s, err)
		}
		addr.Index = int(idx)
	}
	return addr, nil
}
func ParseResourceAddress(s string) (*ResourceAddress, error) {
	matches, err := tokenizeResourceAddress(s)
	if err != nil {
		return nil, err
	}
	mode := config.ManagedResourceMode
	if matches["data_prefix"] != "" {
		mode = config.DataResourceMode
	}
	resourceIndex, err := ParseResourceIndex(matches["index"])
	if err != nil {
		return nil, err
	}
	instanceType, err := ParseInstanceType(matches["instance_type"])
	if err != nil {
		return nil, err
	}
	path := ParseResourcePath(matches["path"])
	if mode == config.DataResourceMode && matches["type"] == "" {
		return nil, fmt.Errorf(
			"invalid resource address %q: must target specific data instance",
			s,
		)
	}
	return &ResourceAddress{
		Path:            path,
		Index:           resourceIndex,
		InstanceType:    instanceType,
		InstanceTypeSet: matches["instance_type"] != "",
		Name:            matches["name"],
		Type:            matches["type"],
		Mode:            mode,
	}, nil
}
func ParseResourceAddressForInstanceDiff(path []string, key string) (*ResourceAddress, error) {
	addr, err := parseResourceAddressInternal(key)
	if err != nil {
		return nil, err
	}
	addr.Path = path
	return addr, nil
}