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 }