github.com/anfernee/terraform@v0.6.16-0.20160430000239-06e5085a92f2/builtin/providers/cloudstack/resource_cloudstack_loadbalancer_rule.go (about) 1 package cloudstack 2 3 import ( 4 "errors" 5 "fmt" 6 "log" 7 "strings" 8 9 "github.com/hashicorp/terraform/helper/schema" 10 "github.com/xanzy/go-cloudstack/cloudstack" 11 ) 12 13 func resourceCloudStackLoadBalancerRule() *schema.Resource { 14 return &schema.Resource{ 15 Create: resourceCloudStackLoadBalancerRuleCreate, 16 Read: resourceCloudStackLoadBalancerRuleRead, 17 Update: resourceCloudStackLoadBalancerRuleUpdate, 18 Delete: resourceCloudStackLoadBalancerRuleDelete, 19 20 Schema: map[string]*schema.Schema{ 21 "name": &schema.Schema{ 22 Type: schema.TypeString, 23 Required: true, 24 }, 25 26 "description": &schema.Schema{ 27 Type: schema.TypeString, 28 Optional: true, 29 Computed: true, 30 }, 31 32 "ip_address_id": &schema.Schema{ 33 Type: schema.TypeString, 34 Optional: true, 35 Computed: true, 36 ForceNew: true, 37 }, 38 39 "ipaddress": &schema.Schema{ 40 Type: schema.TypeString, 41 Optional: true, 42 ForceNew: true, 43 Deprecated: "Please use the `ip_address_id` field instead", 44 }, 45 46 "network_id": &schema.Schema{ 47 Type: schema.TypeString, 48 Optional: true, 49 Computed: true, 50 ForceNew: true, 51 }, 52 53 "network": &schema.Schema{ 54 Type: schema.TypeString, 55 Optional: true, 56 ForceNew: true, 57 Deprecated: "Please use the `network_id` field instead", 58 }, 59 60 "algorithm": &schema.Schema{ 61 Type: schema.TypeString, 62 Required: true, 63 }, 64 65 "private_port": &schema.Schema{ 66 Type: schema.TypeInt, 67 Required: true, 68 ForceNew: true, 69 }, 70 71 "public_port": &schema.Schema{ 72 Type: schema.TypeInt, 73 Required: true, 74 ForceNew: true, 75 }, 76 77 "member_ids": &schema.Schema{ 78 Type: schema.TypeList, 79 Optional: true, 80 ForceNew: true, 81 Elem: &schema.Schema{Type: schema.TypeString}, 82 ConflictsWith: []string{"members"}, 83 }, 84 85 "members": &schema.Schema{ 86 Type: schema.TypeList, 87 Optional: true, 88 ForceNew: true, 89 Elem: &schema.Schema{Type: schema.TypeString}, 90 Deprecated: "Please use the `member_ids` field instead", 91 ConflictsWith: []string{"member_ids"}, 92 }, 93 }, 94 } 95 } 96 97 func resourceCloudStackLoadBalancerRuleCreate(d *schema.ResourceData, meta interface{}) error { 98 cs := meta.(*cloudstack.CloudStackClient) 99 d.Partial(true) 100 101 // Create a new parameter struct 102 p := cs.LoadBalancer.NewCreateLoadBalancerRuleParams( 103 d.Get("algorithm").(string), 104 d.Get("name").(string), 105 d.Get("private_port").(int), 106 d.Get("public_port").(int), 107 ) 108 109 // Don't autocreate a firewall rule, use a resource if needed 110 p.SetOpenfirewall(false) 111 112 // Set the description 113 if description, ok := d.GetOk("description"); ok { 114 p.SetDescription(description.(string)) 115 } else { 116 p.SetDescription(d.Get("name").(string)) 117 } 118 119 network, ok := d.GetOk("network_id") 120 if !ok { 121 network, ok = d.GetOk("network") 122 } 123 if ok { 124 // Retrieve the network ID 125 networkid, e := retrieveID(cs, "network", network.(string)) 126 if e != nil { 127 return e.Error() 128 } 129 130 // Set the networkid 131 p.SetNetworkid(networkid) 132 } 133 134 ipaddress, ok := d.GetOk("ip_address_id") 135 if !ok { 136 ipaddress, ok = d.GetOk("ipaddress") 137 } 138 if !ok { 139 return errors.New("Either `ip_address_id` or [deprecated] `ipaddress` must be provided.") 140 } 141 142 // Retrieve the ipaddress ID 143 ipaddressid, e := retrieveID(cs, "ip_address", ipaddress.(string)) 144 if e != nil { 145 return e.Error() 146 } 147 p.SetPublicipid(ipaddressid) 148 149 // Create the load balancer rule 150 r, err := cs.LoadBalancer.CreateLoadBalancerRule(p) 151 if err != nil { 152 return err 153 } 154 155 // Set the load balancer rule ID and set partials 156 d.SetId(r.Id) 157 d.SetPartial("name") 158 d.SetPartial("description") 159 d.SetPartial("ip_address_id") 160 d.SetPartial("network_id") 161 d.SetPartial("algorithm") 162 d.SetPartial("private_port") 163 d.SetPartial("public_port") 164 165 // Create a new parameter struct 166 ap := cs.LoadBalancer.NewAssignToLoadBalancerRuleParams(r.Id) 167 168 members, ok := d.GetOk("member_ids") 169 if !ok { 170 members, ok = d.GetOk("members") 171 } 172 if !ok { 173 return errors.New("Either `member_ids` or [deprecated] `members` must be provided.") 174 } 175 176 var mbs []string 177 for _, id := range members.([]interface{}) { 178 mbs = append(mbs, id.(string)) 179 } 180 181 ap.SetVirtualmachineids(mbs) 182 183 _, err = cs.LoadBalancer.AssignToLoadBalancerRule(ap) 184 if err != nil { 185 return err 186 } 187 188 d.SetPartial("member_ids") 189 d.SetPartial("members") 190 d.Partial(false) 191 192 return resourceCloudStackLoadBalancerRuleRead(d, meta) 193 } 194 195 func resourceCloudStackLoadBalancerRuleRead(d *schema.ResourceData, meta interface{}) error { 196 cs := meta.(*cloudstack.CloudStackClient) 197 198 // Get the load balancer details 199 lb, count, err := cs.LoadBalancer.GetLoadBalancerRuleByID(d.Id()) 200 if err != nil { 201 if count == 0 { 202 log.Printf("[DEBUG] Load balancer rule %s does no longer exist", d.Get("name").(string)) 203 d.SetId("") 204 return nil 205 } 206 207 return err 208 } 209 210 d.Set("algorithm", lb.Algorithm) 211 d.Set("public_port", lb.Publicport) 212 d.Set("private_port", lb.Privateport) 213 d.Set("ip_address_id", lb.Publicipid) 214 215 // Only set network if user specified it to avoid spurious diffs 216 _, networkID := d.GetOk("network_id") 217 _, network := d.GetOk("network") 218 if networkID || network { 219 d.Set("network_id", lb.Networkid) 220 } 221 222 return nil 223 } 224 225 func resourceCloudStackLoadBalancerRuleUpdate(d *schema.ResourceData, meta interface{}) error { 226 cs := meta.(*cloudstack.CloudStackClient) 227 228 if d.HasChange("name") || d.HasChange("description") || d.HasChange("algorithm") { 229 name := d.Get("name").(string) 230 231 // Create new parameter struct 232 p := cs.LoadBalancer.NewUpdateLoadBalancerRuleParams(d.Id()) 233 234 if d.HasChange("name") { 235 log.Printf("[DEBUG] Name has changed for load balancer rule %s, starting update", name) 236 237 p.SetName(name) 238 } 239 240 if d.HasChange("description") { 241 log.Printf( 242 "[DEBUG] Description has changed for load balancer rule %s, starting update", name) 243 244 p.SetDescription(d.Get("description").(string)) 245 } 246 247 if d.HasChange("algorithm") { 248 algorithm := d.Get("algorithm").(string) 249 250 log.Printf( 251 "[DEBUG] Algorithm has changed to %s for load balancer rule %s, starting update", 252 algorithm, 253 name, 254 ) 255 256 // Set the new Algorithm 257 p.SetAlgorithm(algorithm) 258 } 259 260 _, err := cs.LoadBalancer.UpdateLoadBalancerRule(p) 261 if err != nil { 262 return fmt.Errorf( 263 "Error updating load balancer rule %s", name) 264 } 265 } 266 return resourceCloudStackLoadBalancerRuleRead(d, meta) 267 } 268 269 func resourceCloudStackLoadBalancerRuleDelete(d *schema.ResourceData, meta interface{}) error { 270 cs := meta.(*cloudstack.CloudStackClient) 271 272 // Create a new parameter struct 273 p := cs.LoadBalancer.NewDeleteLoadBalancerRuleParams(d.Id()) 274 275 log.Printf("[INFO] Deleting load balancer rule: %s", d.Get("name").(string)) 276 if _, err := cs.LoadBalancer.DeleteLoadBalancerRule(p); err != nil { 277 // This is a very poor way to be told the ID does no longer exist :( 278 if !strings.Contains(err.Error(), fmt.Sprintf( 279 "Invalid parameter id value=%s due to incorrect long value format, "+ 280 "or entity does not exist", d.Id())) { 281 return err 282 } 283 } 284 285 return nil 286 }