github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/cloudstack/resources.go (about)

     1  package cloudstack
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"regexp"
     7  	"time"
     8  
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  	"github.com/xanzy/go-cloudstack/cloudstack"
    11  )
    12  
    13  // Define a regexp for parsing the port
    14  var splitPorts = regexp.MustCompile(`^(\d+)(?:-(\d+))?$`)
    15  
    16  type retrieveError struct {
    17  	name  string
    18  	value string
    19  	err   error
    20  }
    21  
    22  func (e *retrieveError) Error() error {
    23  	return fmt.Errorf("Error retrieving ID of %s %s: %s", e.name, e.value, e.err)
    24  }
    25  
    26  func setValueOrID(d *schema.ResourceData, key string, value string, id string) {
    27  	if cloudstack.IsID(d.Get(key).(string)) {
    28  		// If the given id is an empty string, check if the configured value matches
    29  		// the UnlimitedResourceID in which case we set id to UnlimitedResourceID
    30  		if id == "" && d.Get(key).(string) == cloudstack.UnlimitedResourceID {
    31  			id = cloudstack.UnlimitedResourceID
    32  		}
    33  
    34  		d.Set(key, id)
    35  	} else {
    36  		d.Set(key, value)
    37  	}
    38  }
    39  
    40  func retrieveID(cs *cloudstack.CloudStackClient, name string, value string, opts ...cloudstack.OptionFunc) (id string, e *retrieveError) {
    41  	// If the supplied value isn't a ID, try to retrieve the ID ourselves
    42  	if cloudstack.IsID(value) {
    43  		return value, nil
    44  	}
    45  
    46  	log.Printf("[DEBUG] Retrieving ID of %s: %s", name, value)
    47  
    48  	// Ignore counts, since an error is returned if there is no exact match
    49  	var err error
    50  	switch name {
    51  	case "disk_offering":
    52  		id, _, err = cs.DiskOffering.GetDiskOfferingID(value)
    53  	case "service_offering":
    54  		id, _, err = cs.ServiceOffering.GetServiceOfferingID(value)
    55  	case "network_offering":
    56  		id, _, err = cs.NetworkOffering.GetNetworkOfferingID(value)
    57  	case "project":
    58  		id, _, err = cs.Project.GetProjectID(value)
    59  	case "vpc_offering":
    60  		id, _, err = cs.VPC.GetVPCOfferingID(value)
    61  	case "zone":
    62  		id, _, err = cs.Zone.GetZoneID(value)
    63  	case "os_type":
    64  		p := cs.GuestOS.NewListOsTypesParams()
    65  		p.SetDescription(value)
    66  		l, e := cs.GuestOS.ListOsTypes(p)
    67  		if e != nil {
    68  			err = e
    69  			break
    70  		}
    71  		if l.Count == 1 {
    72  			id = l.OsTypes[0].Id
    73  			break
    74  		}
    75  		err = fmt.Errorf("Could not find ID of OS Type: %s", value)
    76  	default:
    77  		return id, &retrieveError{name: name, value: value,
    78  			err: fmt.Errorf("Unknown request: %s", name)}
    79  	}
    80  
    81  	if err != nil {
    82  		return id, &retrieveError{name: name, value: value, err: err}
    83  	}
    84  
    85  	return id, nil
    86  }
    87  
    88  func retrieveTemplateID(cs *cloudstack.CloudStackClient, zoneid, value string) (id string, e *retrieveError) {
    89  	// If the supplied value isn't a ID, try to retrieve the ID ourselves
    90  	if cloudstack.IsID(value) {
    91  		return value, nil
    92  	}
    93  
    94  	log.Printf("[DEBUG] Retrieving ID of template: %s", value)
    95  
    96  	// Ignore count, since an error is returned if there is no exact match
    97  	id, _, err := cs.Template.GetTemplateID(value, "executable", zoneid)
    98  	if err != nil {
    99  		return id, &retrieveError{name: "template", value: value, err: err}
   100  	}
   101  
   102  	return id, nil
   103  }
   104  
   105  // RetryFunc is the function retried n times
   106  type RetryFunc func() (interface{}, error)
   107  
   108  // Retry is a wrapper around a RetryFunc that will retry a function
   109  // n times or until it succeeds.
   110  func Retry(n int, f RetryFunc) (interface{}, error) {
   111  	var lastErr error
   112  
   113  	for i := 0; i < n; i++ {
   114  		r, err := f()
   115  		if err == nil || err == cloudstack.AsyncTimeoutErr {
   116  			return r, err
   117  		}
   118  
   119  		lastErr = err
   120  		time.Sleep(30 * time.Second)
   121  	}
   122  
   123  	return nil, lastErr
   124  }
   125  
   126  // If there is a project supplied, we retrieve and set the project id
   127  func setProjectid(p cloudstack.ProjectIDSetter, cs *cloudstack.CloudStackClient, d *schema.ResourceData) error {
   128  	if project, ok := d.GetOk("project"); ok {
   129  		projectid, e := retrieveID(cs, "project", project.(string))
   130  		if e != nil {
   131  			return e.Error()
   132  		}
   133  		p.SetProjectid(projectid)
   134  	}
   135  
   136  	return nil
   137  }