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 }