github.com/tarrant/terraform@v0.3.8-0.20150402012457-f68c9eee638e/builtin/providers/openstack/resource_openstack_lb_pool_v1.go (about)

     1  package openstack
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  
     8  	"github.com/hashicorp/terraform/helper/hashcode"
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members"
    11  	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
    12  	"github.com/rackspace/gophercloud/pagination"
    13  )
    14  
    15  func resourceLBPoolV1() *schema.Resource {
    16  	return &schema.Resource{
    17  		Create: resourceLBPoolV1Create,
    18  		Read:   resourceLBPoolV1Read,
    19  		Update: resourceLBPoolV1Update,
    20  		Delete: resourceLBPoolV1Delete,
    21  
    22  		Schema: map[string]*schema.Schema{
    23  			"region": &schema.Schema{
    24  				Type:        schema.TypeString,
    25  				Required:    true,
    26  				ForceNew:    true,
    27  				DefaultFunc: envDefaultFunc("OS_REGION_NAME"),
    28  			},
    29  			"name": &schema.Schema{
    30  				Type:     schema.TypeString,
    31  				Required: true,
    32  				ForceNew: false,
    33  			},
    34  			"protocol": &schema.Schema{
    35  				Type:     schema.TypeString,
    36  				Required: true,
    37  				ForceNew: true,
    38  			},
    39  			"subnet_id": &schema.Schema{
    40  				Type:     schema.TypeString,
    41  				Required: true,
    42  				ForceNew: true,
    43  			},
    44  
    45  			"lb_method": &schema.Schema{
    46  				Type:     schema.TypeString,
    47  				Required: true,
    48  				ForceNew: false,
    49  			},
    50  			"tenant_id": &schema.Schema{
    51  				Type:     schema.TypeString,
    52  				Optional: true,
    53  				ForceNew: true,
    54  			},
    55  			"member": &schema.Schema{
    56  				Type:     schema.TypeSet,
    57  				Optional: true,
    58  				Elem: &schema.Resource{
    59  					Schema: map[string]*schema.Schema{
    60  						"region": &schema.Schema{
    61  							Type:        schema.TypeString,
    62  							Required:    true,
    63  							ForceNew:    true,
    64  							DefaultFunc: envDefaultFunc("OS_REGION_NAME"),
    65  						},
    66  						"tenant_id": &schema.Schema{
    67  							Type:     schema.TypeString,
    68  							Optional: true,
    69  							ForceNew: true,
    70  						},
    71  						"address": &schema.Schema{
    72  							Type:     schema.TypeString,
    73  							Required: true,
    74  							ForceNew: true,
    75  						},
    76  						"port": &schema.Schema{
    77  							Type:     schema.TypeInt,
    78  							Required: true,
    79  							ForceNew: true,
    80  						},
    81  						"admin_state_up": &schema.Schema{
    82  							Type:     schema.TypeBool,
    83  							Required: true,
    84  							ForceNew: false,
    85  						},
    86  					},
    87  				},
    88  				Set: resourceLBMemberV1Hash,
    89  			},
    90  			"monitor_ids": &schema.Schema{
    91  				Type:     schema.TypeSet,
    92  				Optional: true,
    93  				ForceNew: false,
    94  				Elem:     &schema.Schema{Type: schema.TypeString},
    95  				Set: func(v interface{}) int {
    96  					return hashcode.String(v.(string))
    97  				},
    98  			},
    99  		},
   100  	}
   101  }
   102  
   103  func resourceLBPoolV1Create(d *schema.ResourceData, meta interface{}) error {
   104  	config := meta.(*Config)
   105  	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
   106  	if err != nil {
   107  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   108  	}
   109  
   110  	createOpts := pools.CreateOpts{
   111  		Name:     d.Get("name").(string),
   112  		Protocol: d.Get("protocol").(string),
   113  		SubnetID: d.Get("subnet_id").(string),
   114  		LBMethod: d.Get("lb_method").(string),
   115  		TenantID: d.Get("tenant_id").(string),
   116  	}
   117  
   118  	log.Printf("[DEBUG] Create Options: %#v", createOpts)
   119  	p, err := pools.Create(networkingClient, createOpts).Extract()
   120  	if err != nil {
   121  		return fmt.Errorf("Error creating OpenStack LB pool: %s", err)
   122  	}
   123  	log.Printf("[INFO] LB Pool ID: %s", p.ID)
   124  
   125  	d.SetId(p.ID)
   126  
   127  	if mIDs := resourcePoolMonitorIDsV1(d); mIDs != nil {
   128  		for _, mID := range mIDs {
   129  			_, err := pools.AssociateMonitor(networkingClient, p.ID, mID).Extract()
   130  			if err != nil {
   131  				return fmt.Errorf("Error associating monitor (%s) with OpenStack LB pool (%s): %s", mID, p.ID, err)
   132  			}
   133  		}
   134  	}
   135  
   136  	if memberOpts := resourcePoolMembersV1(d); memberOpts != nil {
   137  		for _, memberOpt := range memberOpts {
   138  			_, err := members.Create(networkingClient, memberOpt).Extract()
   139  			if err != nil {
   140  				return fmt.Errorf("Error creating OpenStack LB member: %s", err)
   141  			}
   142  		}
   143  	}
   144  
   145  	return resourceLBPoolV1Read(d, meta)
   146  }
   147  
   148  func resourceLBPoolV1Read(d *schema.ResourceData, meta interface{}) error {
   149  	config := meta.(*Config)
   150  	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
   151  	if err != nil {
   152  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   153  	}
   154  
   155  	p, err := pools.Get(networkingClient, d.Id()).Extract()
   156  	if err != nil {
   157  		return CheckDeleted(d, err, "LB pool")
   158  	}
   159  
   160  	log.Printf("[DEBUG] Retreived OpenStack LB Pool %s: %+v", d.Id(), p)
   161  
   162  	d.Set("name", p.Name)
   163  	d.Set("protocol", p.Protocol)
   164  	d.Set("subnet_id", p.SubnetID)
   165  	d.Set("lb_method", p.LBMethod)
   166  	d.Set("tenant_id", p.TenantID)
   167  	d.Set("monitor_ids", p.MonitorIDs)
   168  	d.Set("member_ids", p.MemberIDs)
   169  
   170  	return nil
   171  }
   172  
   173  func resourceLBPoolV1Update(d *schema.ResourceData, meta interface{}) error {
   174  	config := meta.(*Config)
   175  	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
   176  	if err != nil {
   177  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   178  	}
   179  
   180  	var updateOpts pools.UpdateOpts
   181  	if d.HasChange("name") {
   182  		updateOpts.Name = d.Get("name").(string)
   183  	}
   184  	if d.HasChange("lb_method") {
   185  		updateOpts.LBMethod = d.Get("lb_method").(string)
   186  	}
   187  
   188  	log.Printf("[DEBUG] Updating OpenStack LB Pool %s with options: %+v", d.Id(), updateOpts)
   189  
   190  	_, err = pools.Update(networkingClient, d.Id(), updateOpts).Extract()
   191  	if err != nil {
   192  		return fmt.Errorf("Error updating OpenStack LB Pool: %s", err)
   193  	}
   194  
   195  	if d.HasChange("monitor_ids") {
   196  		oldMIDsRaw, newMIDsRaw := d.GetChange("security_groups")
   197  		oldMIDsSet, newMIDsSet := oldMIDsRaw.(*schema.Set), newMIDsRaw.(*schema.Set)
   198  		monitorsToAdd := newMIDsSet.Difference(oldMIDsSet)
   199  		monitorsToRemove := oldMIDsSet.Difference(newMIDsSet)
   200  
   201  		log.Printf("[DEBUG] Monitors to add: %v", monitorsToAdd)
   202  
   203  		log.Printf("[DEBUG] Monitors to remove: %v", monitorsToRemove)
   204  
   205  		for _, m := range monitorsToAdd.List() {
   206  			_, err := pools.AssociateMonitor(networkingClient, d.Id(), m.(string)).Extract()
   207  			if err != nil {
   208  				return fmt.Errorf("Error associating monitor (%s) with OpenStack server (%s): %s", m.(string), d.Id(), err)
   209  			}
   210  			log.Printf("[DEBUG] Associated monitor (%s) with pool (%s)", m.(string), d.Id())
   211  		}
   212  
   213  		for _, m := range monitorsToRemove.List() {
   214  			_, err := pools.DisassociateMonitor(networkingClient, d.Id(), m.(string)).Extract()
   215  			if err != nil {
   216  				return fmt.Errorf("Error disassociating monitor (%s) from OpenStack server (%s): %s", m.(string), d.Id(), err)
   217  			}
   218  			log.Printf("[DEBUG] Disassociated monitor (%s) from pool (%s)", m.(string), d.Id())
   219  		}
   220  	}
   221  
   222  	if d.HasChange("member") {
   223  		oldMembersRaw, newMembersRaw := d.GetChange("member")
   224  		oldMembersSet, newMembersSet := oldMembersRaw.(*schema.Set), newMembersRaw.(*schema.Set)
   225  		membersToAdd := newMembersSet.Difference(oldMembersSet)
   226  		membersToRemove := oldMembersSet.Difference(newMembersSet)
   227  
   228  		log.Printf("[DEBUG] Members to add: %v", membersToAdd)
   229  
   230  		log.Printf("[DEBUG] Members to remove: %v", membersToRemove)
   231  
   232  		for _, m := range membersToRemove.List() {
   233  			oldMember := resourcePoolMemberV1(d, m)
   234  			listOpts := members.ListOpts{
   235  				PoolID:       d.Id(),
   236  				Address:      oldMember.Address,
   237  				ProtocolPort: oldMember.ProtocolPort,
   238  			}
   239  			err = members.List(networkingClient, listOpts).EachPage(func(page pagination.Page) (bool, error) {
   240  				extractedMembers, err := members.ExtractMembers(page)
   241  				if err != nil {
   242  					return false, err
   243  				}
   244  				for _, member := range extractedMembers {
   245  					err := members.Delete(networkingClient, member.ID).ExtractErr()
   246  					if err != nil {
   247  						return false, fmt.Errorf("Error deleting member (%s) from OpenStack LB pool (%s): %s", member.ID, d.Id(), err)
   248  					}
   249  					log.Printf("[DEBUG] Deleted member (%s) from pool (%s)", member.ID, d.Id())
   250  				}
   251  				return true, nil
   252  			})
   253  		}
   254  
   255  		for _, m := range membersToAdd.List() {
   256  			createOpts := resourcePoolMemberV1(d, m)
   257  			newMember, err := members.Create(networkingClient, createOpts).Extract()
   258  			if err != nil {
   259  				return fmt.Errorf("Error creating LB member: %s", err)
   260  			}
   261  			log.Printf("[DEBUG] Created member (%s) in OpenStack LB pool (%s)", newMember.ID, d.Id())
   262  		}
   263  	}
   264  
   265  	return resourceLBPoolV1Read(d, meta)
   266  }
   267  
   268  func resourceLBPoolV1Delete(d *schema.ResourceData, meta interface{}) error {
   269  	config := meta.(*Config)
   270  	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
   271  	if err != nil {
   272  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   273  	}
   274  
   275  	err = pools.Delete(networkingClient, d.Id()).ExtractErr()
   276  	if err != nil {
   277  		return fmt.Errorf("Error deleting OpenStack LB Pool: %s", err)
   278  	}
   279  
   280  	d.SetId("")
   281  	return nil
   282  }
   283  
   284  func resourcePoolMonitorIDsV1(d *schema.ResourceData) []string {
   285  	mIDsRaw := d.Get("monitor_ids").(*schema.Set)
   286  	mIDs := make([]string, mIDsRaw.Len())
   287  	for i, raw := range mIDsRaw.List() {
   288  		mIDs[i] = raw.(string)
   289  	}
   290  	return mIDs
   291  }
   292  
   293  func resourcePoolMembersV1(d *schema.ResourceData) []members.CreateOpts {
   294  	memberOptsRaw := (d.Get("member")).(*schema.Set)
   295  	memberOpts := make([]members.CreateOpts, memberOptsRaw.Len())
   296  	for i, raw := range memberOptsRaw.List() {
   297  		rawMap := raw.(map[string]interface{})
   298  		memberOpts[i] = members.CreateOpts{
   299  			TenantID:     rawMap["tenant_id"].(string),
   300  			Address:      rawMap["address"].(string),
   301  			ProtocolPort: rawMap["port"].(int),
   302  			PoolID:       d.Id(),
   303  		}
   304  	}
   305  	return memberOpts
   306  }
   307  
   308  func resourcePoolMemberV1(d *schema.ResourceData, raw interface{}) members.CreateOpts {
   309  	rawMap := raw.(map[string]interface{})
   310  	return members.CreateOpts{
   311  		TenantID:     rawMap["tenant_id"].(string),
   312  		Address:      rawMap["address"].(string),
   313  		ProtocolPort: rawMap["port"].(int),
   314  		PoolID:       d.Id(),
   315  	}
   316  }
   317  
   318  func resourceLBMemberV1Hash(v interface{}) int {
   319  	var buf bytes.Buffer
   320  	m := v.(map[string]interface{})
   321  	buf.WriteString(fmt.Sprintf("%s-", m["region"].(string)))
   322  	buf.WriteString(fmt.Sprintf("%s-", m["tenant_id"].(string)))
   323  	buf.WriteString(fmt.Sprintf("%s-", m["address"].(string)))
   324  	buf.WriteString(fmt.Sprintf("%d-", m["port"].(int)))
   325  
   326  	return hashcode.String(buf.String())
   327  }