github.com/nicgrayson/terraform@v0.4.3-0.20150415203910-c4de50829380/terraform/resource_address.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  	"strconv"
     7  )
     8  
     9  // ResourceAddress is a way of identifying an individual resource (or,
    10  // eventually, a subset of resources) within the state. It is used for Targets.
    11  type ResourceAddress struct {
    12  	Index        int
    13  	InstanceType InstanceType
    14  	Name         string
    15  	Type         string
    16  }
    17  
    18  func ParseResourceAddress(s string) (*ResourceAddress, error) {
    19  	matches, err := tokenizeResourceAddress(s)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  	resourceIndex := -1
    24  	if matches["index"] != "" {
    25  		var err error
    26  		if resourceIndex, err = strconv.Atoi(matches["index"]); err != nil {
    27  			return nil, err
    28  		}
    29  	}
    30  	instanceType := TypePrimary
    31  	if matches["instance_type"] != "" {
    32  		var err error
    33  		if instanceType, err = ParseInstanceType(matches["instance_type"]); err != nil {
    34  			return nil, err
    35  		}
    36  	}
    37  
    38  	return &ResourceAddress{
    39  		Index:        resourceIndex,
    40  		InstanceType: instanceType,
    41  		Name:         matches["name"],
    42  		Type:         matches["type"],
    43  	}, nil
    44  }
    45  
    46  func (addr *ResourceAddress) Equals(raw interface{}) bool {
    47  	other, ok := raw.(*ResourceAddress)
    48  	if !ok {
    49  		return false
    50  	}
    51  
    52  	indexMatch := (addr.Index == -1 ||
    53  		other.Index == -1 ||
    54  		addr.Index == other.Index)
    55  
    56  	return (indexMatch &&
    57  		addr.InstanceType == other.InstanceType &&
    58  		addr.Name == other.Name &&
    59  		addr.Type == other.Type)
    60  }
    61  
    62  func ParseInstanceType(s string) (InstanceType, error) {
    63  	switch s {
    64  	case "primary":
    65  		return TypePrimary, nil
    66  	case "deposed":
    67  		return TypeDeposed, nil
    68  	case "tainted":
    69  		return TypeTainted, nil
    70  	default:
    71  		return TypeInvalid, fmt.Errorf("Unexpected value for InstanceType field: %q", s)
    72  	}
    73  }
    74  
    75  func tokenizeResourceAddress(s string) (map[string]string, error) {
    76  	// Example of portions of the regexp below using the
    77  	// string "aws_instance.web.tainted[1]"
    78  	re := regexp.MustCompile(`\A` +
    79  		// "aws_instance"
    80  		`(?P<type>\w+)\.` +
    81  		// "web"
    82  		`(?P<name>\w+)` +
    83  		// "tainted" (optional, omission implies: "primary")
    84  		`(?:\.(?P<instance_type>\w+))?` +
    85  		// "1" (optional, omission implies: "0")
    86  		`(?:\[(?P<index>\d+)\])?` +
    87  		`\z`)
    88  	groupNames := re.SubexpNames()
    89  	rawMatches := re.FindAllStringSubmatch(s, -1)
    90  	if len(rawMatches) != 1 {
    91  		return nil, fmt.Errorf("Problem parsing address: %q", s)
    92  	}
    93  	matches := make(map[string]string)
    94  	for i, m := range rawMatches[0] {
    95  		matches[groupNames[i]] = m
    96  	}
    97  	return matches, nil
    98  }