github.com/leeprovoost/terraform@v0.6.10-0.20160119085442-96f3f76118e7/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 }