github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/google/resource_compute_instance_group_manager.go (about)

     1  package google
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  
     8  	"google.golang.org/api/compute/v1"
     9  	"google.golang.org/api/googleapi"
    10  
    11  	"github.com/hashicorp/terraform/helper/hashcode"
    12  	"github.com/hashicorp/terraform/helper/schema"
    13  )
    14  
    15  func resourceComputeInstanceGroupManager() *schema.Resource {
    16  	return &schema.Resource{
    17  		Create: resourceComputeInstanceGroupManagerCreate,
    18  		Read:   resourceComputeInstanceGroupManagerRead,
    19  		Update: resourceComputeInstanceGroupManagerUpdate,
    20  		Delete: resourceComputeInstanceGroupManagerDelete,
    21  
    22  		Schema: map[string]*schema.Schema{
    23  			"name": &schema.Schema{
    24  				Type:     schema.TypeString,
    25  				Required: true,
    26  				ForceNew: true,
    27  			},
    28  
    29  			"description": &schema.Schema{
    30  				Type:     schema.TypeString,
    31  				Optional: true,
    32  				ForceNew: true,
    33  			},
    34  
    35  			"base_instance_name": &schema.Schema{
    36  				Type:     schema.TypeString,
    37  				Required: true,
    38  				ForceNew: true,
    39  			},
    40  
    41  			"fingerprint": &schema.Schema{
    42  				Type:     schema.TypeString,
    43  				Computed: true,
    44  			},
    45  
    46  			"instance_group": &schema.Schema{
    47  				Type:     schema.TypeString,
    48  				Computed: true,
    49  			},
    50  
    51  			"instance_template": &schema.Schema{
    52  				Type:     schema.TypeString,
    53  				Required: true,
    54  			},
    55  
    56  			"target_pools": &schema.Schema{
    57  				Type:     schema.TypeSet,
    58  				Optional: true,
    59  				Elem:     &schema.Schema{Type: schema.TypeString},
    60  				Set: func(v interface{}) int {
    61  					return hashcode.String(v.(string))
    62  				},
    63  			},
    64  
    65  			"target_size": &schema.Schema{
    66  				Type:     schema.TypeInt,
    67  				Computed: true,
    68  				Optional: true,
    69  			},
    70  
    71  			"zone": &schema.Schema{
    72  				Type:     schema.TypeString,
    73  				Required: true,
    74  				ForceNew: true,
    75  			},
    76  
    77  			"self_link": &schema.Schema{
    78  				Type:     schema.TypeString,
    79  				Computed: true,
    80  			},
    81  		},
    82  	}
    83  }
    84  
    85  func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta interface{}) error {
    86  	config := meta.(*Config)
    87  
    88  	// Get group size, default to 1 if not given
    89  	var target_size int64 = 1
    90  	if v, ok := d.GetOk("target_size"); ok {
    91  		target_size = int64(v.(int))
    92  	}
    93  
    94  	// Build the parameter
    95  	manager := &compute.InstanceGroupManager{
    96  		Name:             d.Get("name").(string),
    97  		BaseInstanceName: d.Get("base_instance_name").(string),
    98  		InstanceTemplate: d.Get("instance_template").(string),
    99  		TargetSize:       target_size,
   100  	}
   101  
   102  	// Set optional fields
   103  	if v, ok := d.GetOk("description"); ok {
   104  		manager.Description = v.(string)
   105  	}
   106  
   107  	if attr := d.Get("target_pools").(*schema.Set); attr.Len() > 0 {
   108  		var s []string
   109  		for _, v := range attr.List() {
   110  			s = append(s, v.(string))
   111  		}
   112  		manager.TargetPools = s
   113  	}
   114  
   115  	log.Printf("[DEBUG] InstanceGroupManager insert request: %#v", manager)
   116  	op, err := config.clientCompute.InstanceGroupManagers.Insert(
   117  		config.Project, d.Get("zone").(string), manager).Do()
   118  	if err != nil {
   119  		return fmt.Errorf("Error creating InstanceGroupManager: %s", err)
   120  	}
   121  
   122  	// It probably maybe worked, so store the ID now
   123  	d.SetId(manager.Name)
   124  
   125  	// Wait for the operation to complete
   126  	err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Creating InstanceGroupManager")
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	return resourceComputeInstanceGroupManagerRead(d, meta)
   132  }
   133  
   134  func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interface{}) error {
   135  	config := meta.(*Config)
   136  
   137  	manager, err := config.clientCompute.InstanceGroupManagers.Get(
   138  		config.Project, d.Get("zone").(string), d.Id()).Do()
   139  	if err != nil {
   140  		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
   141  			// The resource doesn't exist anymore
   142  			d.SetId("")
   143  
   144  			return nil
   145  		}
   146  
   147  		return fmt.Errorf("Error reading instance group manager: %s", err)
   148  	}
   149  
   150  	// Set computed fields
   151  	d.Set("fingerprint", manager.Fingerprint)
   152  	d.Set("instance_group", manager.InstanceGroup)
   153  	d.Set("target_size", manager.TargetSize)
   154  	d.Set("self_link", manager.SelfLink)
   155  
   156  	return nil
   157  }
   158  func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error {
   159  	config := meta.(*Config)
   160  
   161  	d.Partial(true)
   162  
   163  	// If target_pools changes then update
   164  	if d.HasChange("target_pools") {
   165  		var targetPools []string
   166  		if attr := d.Get("target_pools").(*schema.Set); attr.Len() > 0 {
   167  			for _, v := range attr.List() {
   168  				targetPools = append(targetPools, v.(string))
   169  			}
   170  		}
   171  
   172  		// Build the parameter
   173  		setTargetPools := &compute.InstanceGroupManagersSetTargetPoolsRequest{
   174  			Fingerprint: d.Get("fingerprint").(string),
   175  			TargetPools: targetPools,
   176  		}
   177  
   178  		op, err := config.clientCompute.InstanceGroupManagers.SetTargetPools(
   179  			config.Project, d.Get("zone").(string), d.Id(), setTargetPools).Do()
   180  		if err != nil {
   181  			return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
   182  		}
   183  
   184  		// Wait for the operation to complete
   185  		err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager")
   186  		if err != nil {
   187  			return err
   188  		}
   189  
   190  		d.SetPartial("target_pools")
   191  	}
   192  
   193  	// If instance_template changes then update
   194  	if d.HasChange("instance_template") {
   195  		// Build the parameter
   196  		setInstanceTemplate := &compute.InstanceGroupManagersSetInstanceTemplateRequest{
   197  			InstanceTemplate: d.Get("instance_template").(string),
   198  		}
   199  
   200  		op, err := config.clientCompute.InstanceGroupManagers.SetInstanceTemplate(
   201  			config.Project, d.Get("zone").(string), d.Id(), setInstanceTemplate).Do()
   202  		if err != nil {
   203  			return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
   204  		}
   205  
   206  		// Wait for the operation to complete
   207  		err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager")
   208  		if err != nil {
   209  			return err
   210  		}
   211  
   212  		d.SetPartial("instance_template")
   213  	}
   214  
   215  	// If size changes trigger a resize
   216  	if d.HasChange("target_size") {
   217  		if v, ok := d.GetOk("target_size"); ok {
   218  			// Only do anything if the new size is set
   219  			target_size := int64(v.(int))
   220  
   221  			op, err := config.clientCompute.InstanceGroupManagers.Resize(
   222  				config.Project, d.Get("zone").(string), d.Id(), target_size).Do()
   223  			if err != nil {
   224  				return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
   225  			}
   226  
   227  			// Wait for the operation to complete
   228  			err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager")
   229  			if err != nil {
   230  				return err
   231  			}
   232  		}
   233  
   234  		d.SetPartial("target_size")
   235  	}
   236  
   237  	d.Partial(false)
   238  
   239  	return resourceComputeInstanceGroupManagerRead(d, meta)
   240  }
   241  
   242  func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta interface{}) error {
   243  	config := meta.(*Config)
   244  
   245  	zone := d.Get("zone").(string)
   246  	op, err := config.clientCompute.InstanceGroupManagers.Delete(config.Project, zone, d.Id()).Do()
   247  	if err != nil {
   248  		return fmt.Errorf("Error deleting instance group manager: %s", err)
   249  	}
   250  
   251  	currentSize := int64(d.Get("target_size").(int))
   252  
   253  	// Wait for the operation to complete
   254  	err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Deleting InstanceGroupManager")
   255  
   256  	for err != nil && currentSize > 0 {
   257  		if !strings.Contains(err.Error(), "timeout") {
   258  			return err
   259  		}
   260  
   261  		instanceGroup, err := config.clientCompute.InstanceGroups.Get(
   262  			config.Project, d.Get("zone").(string), d.Id()).Do()
   263  
   264  		if err != nil {
   265  			return fmt.Errorf("Error getting instance group size: %s", err)
   266  		}
   267  
   268  		if instanceGroup.Size >= currentSize {
   269  			return fmt.Errorf("Error, instance group isn't shrinking during delete")
   270  		}
   271  
   272  		log.Printf("[INFO] timeout occured, but instance group is shrinking (%d < %d)", instanceGroup.Size, currentSize)
   273  
   274  		currentSize = instanceGroup.Size
   275  
   276  		err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Deleting InstanceGroupManager")
   277  	}
   278  
   279  	d.SetId("")
   280  	return nil
   281  }