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