github.com/erriapo/terraform@v0.6.12-0.20160203182612-0340ea72354f/builtin/providers/cloudstack/resources.go (about)

     1  package cloudstack
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"regexp"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  	"github.com/xanzy/go-cloudstack/cloudstack"
    12  )
    13  
    14  // UnlimitedResourceID is a "special" ID to define an unlimited resource
    15  const UnlimitedResourceID = "-1"
    16  
    17  // Define a regexp for parsing the port
    18  var splitPorts = regexp.MustCompile(`^(\d+)(?:-(\d+))?$`)
    19  
    20  type retrieveError struct {
    21  	name  string
    22  	value string
    23  	err   error
    24  }
    25  
    26  func (e *retrieveError) Error() error {
    27  	return fmt.Errorf("Error retrieving ID of %s %s: %s", e.name, e.value, e.err)
    28  }
    29  
    30  func setValueOrID(d *schema.ResourceData, key string, value string, id string) {
    31  	if isID(d.Get(key).(string)) {
    32  		// If the given id is an empty string, check if the configured value matches
    33  		// the UnlimitedResourceID in which case we set id to UnlimitedResourceID
    34  		if id == "" && d.Get(key).(string) == UnlimitedResourceID {
    35  			id = UnlimitedResourceID
    36  		}
    37  
    38  		d.Set(key, id)
    39  	} else {
    40  		d.Set(key, value)
    41  	}
    42  }
    43  
    44  func retrieveID(cs *cloudstack.CloudStackClient, name, value string) (id string, e *retrieveError) {
    45  	// If the supplied value isn't a ID, try to retrieve the ID ourselves
    46  	if isID(value) {
    47  		return value, nil
    48  	}
    49  
    50  	log.Printf("[DEBUG] Retrieving ID of %s: %s", name, value)
    51  
    52  	var err error
    53  	switch name {
    54  	case "disk_offering":
    55  		id, err = cs.DiskOffering.GetDiskOfferingID(value)
    56  	case "virtual_machine":
    57  		id, err = cs.VirtualMachine.GetVirtualMachineID(value)
    58  	case "service_offering":
    59  		id, err = cs.ServiceOffering.GetServiceOfferingID(value)
    60  	case "network_offering":
    61  		id, err = cs.NetworkOffering.GetNetworkOfferingID(value)
    62  	case "project":
    63  		id, err = cs.Project.GetProjectID(value)
    64  	case "vpc_offering":
    65  		id, err = cs.VPC.GetVPCOfferingID(value)
    66  	case "vpc":
    67  		id, err = cs.VPC.GetVPCID(value)
    68  	case "network":
    69  		id, err = cs.Network.GetNetworkID(value)
    70  	case "zone":
    71  		id, err = cs.Zone.GetZoneID(value)
    72  	case "ipaddress":
    73  		p := cs.Address.NewListPublicIpAddressesParams()
    74  		p.SetIpaddress(value)
    75  		l, e := cs.Address.ListPublicIpAddresses(p)
    76  		if e != nil {
    77  			err = e
    78  			break
    79  		}
    80  		if l.Count == 1 {
    81  			id = l.PublicIpAddresses[0].Id
    82  			break
    83  		}
    84  		err = fmt.Errorf("Could not find ID of IP address: %s", value)
    85  	case "os_type":
    86  		p := cs.GuestOS.NewListOsTypesParams()
    87  		p.SetDescription(value)
    88  		l, e := cs.GuestOS.ListOsTypes(p)
    89  		if e != nil {
    90  			err = e
    91  			break
    92  		}
    93  		if l.Count == 1 {
    94  			id = l.OsTypes[0].Id
    95  			break
    96  		}
    97  		err = fmt.Errorf("Could not find ID of OS Type: %s", value)
    98  	default:
    99  		return id, &retrieveError{name: name, value: value,
   100  			err: fmt.Errorf("Unknown request: %s", name)}
   101  	}
   102  
   103  	if err != nil {
   104  		return id, &retrieveError{name: name, value: value, err: err}
   105  	}
   106  
   107  	return id, nil
   108  }
   109  
   110  func retrieveTemplateID(cs *cloudstack.CloudStackClient, zoneid, value string) (id string, e *retrieveError) {
   111  	// If the supplied value isn't a ID, try to retrieve the ID ourselves
   112  	if isID(value) {
   113  		return value, nil
   114  	}
   115  
   116  	log.Printf("[DEBUG] Retrieving ID of template: %s", value)
   117  
   118  	id, err := cs.Template.GetTemplateID(value, "executable", zoneid)
   119  	if err != nil {
   120  		return id, &retrieveError{name: "template", value: value, err: err}
   121  	}
   122  
   123  	return id, nil
   124  }
   125  
   126  // ID can be either a UUID or a UnlimitedResourceID
   127  func isID(id string) bool {
   128  	re := regexp.MustCompile(`^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|-1)$`)
   129  	return re.MatchString(id)
   130  }
   131  
   132  // RetryFunc is the function retried n times
   133  type RetryFunc func() (interface{}, error)
   134  
   135  // Retry is a wrapper around a RetryFunc that will retry a function
   136  // n times or until it succeeds.
   137  func Retry(n int, f RetryFunc) (interface{}, error) {
   138  	var lastErr error
   139  
   140  	for i := 0; i < n; i++ {
   141  		r, err := f()
   142  		if err == nil || err == cloudstack.AsyncTimeoutErr {
   143  			return r, err
   144  		}
   145  
   146  		lastErr = err
   147  		time.Sleep(30 * time.Second)
   148  	}
   149  
   150  	return nil, lastErr
   151  }
   152  
   153  // This is a temporary helper function to support both the new
   154  // cidr_list and the deprecated source_cidr parameter
   155  func retrieveCidrList(rule map[string]interface{}) []string {
   156  	sourceCidr := rule["source_cidr"].(string)
   157  	if sourceCidr != "" {
   158  		return []string{sourceCidr}
   159  	}
   160  
   161  	var cidrList []string
   162  	for _, cidr := range rule["cidr_list"].(*schema.Set).List() {
   163  		cidrList = append(cidrList, cidr.(string))
   164  	}
   165  
   166  	return cidrList
   167  }
   168  
   169  // This is a temporary helper function to support both the new
   170  // cidr_list and the deprecated source_cidr parameter
   171  func setCidrList(rule map[string]interface{}, cidrList string) {
   172  	sourceCidr := rule["source_cidr"].(string)
   173  	if sourceCidr != "" {
   174  		rule["source_cidr"] = cidrList
   175  		return
   176  	}
   177  
   178  	cidrs := &schema.Set{F: schema.HashString}
   179  	for _, cidr := range strings.Split(cidrList, ",") {
   180  		cidrs.Add(cidr)
   181  	}
   182  
   183  	rule["cidr_list"] = cidrs
   184  }