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  }