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