github.com/leeprovoost/terraform@v0.6.10-0.20160119085442-96f3f76118e7/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  			"update_strategy": &schema.Schema{
    57  				Type:     schema.TypeString,
    58  				Optional: true,
    59  				Default:  "RESTART",
    60  			},
    61  
    62  			"target_pools": &schema.Schema{
    63  				Type:     schema.TypeSet,
    64  				Optional: true,
    65  				Elem:     &schema.Schema{Type: schema.TypeString},
    66  				Set: func(v interface{}) int {
    67  					return hashcode.String(v.(string))
    68  				},
    69  			},
    70  
    71  			"target_size": &schema.Schema{
    72  				Type:     schema.TypeInt,
    73  				Computed: true,
    74  				Optional: true,
    75  			},
    76  
    77  			"zone": &schema.Schema{
    78  				Type:     schema.TypeString,
    79  				Required: true,
    80  				ForceNew: true,
    81  			},
    82  
    83  			"self_link": &schema.Schema{
    84  				Type:     schema.TypeString,
    85  				Computed: true,
    86  			},
    87  		},
    88  	}
    89  }
    90  
    91  func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta interface{}) error {
    92  	config := meta.(*Config)
    93  
    94  	// Get group size, default to 1 if not given
    95  	var target_size int64 = 1
    96  	if v, ok := d.GetOk("target_size"); ok {
    97  		target_size = int64(v.(int))
    98  	}
    99  
   100  	// Build the parameter
   101  	manager := &compute.InstanceGroupManager{
   102  		Name:             d.Get("name").(string),
   103  		BaseInstanceName: d.Get("base_instance_name").(string),
   104  		InstanceTemplate: d.Get("instance_template").(string),
   105  		TargetSize:       target_size,
   106  	}
   107  
   108  	// Set optional fields
   109  	if v, ok := d.GetOk("description"); ok {
   110  		manager.Description = v.(string)
   111  	}
   112  
   113  	if attr := d.Get("target_pools").(*schema.Set); attr.Len() > 0 {
   114  		var s []string
   115  		for _, v := range attr.List() {
   116  			s = append(s, v.(string))
   117  		}
   118  		manager.TargetPools = s
   119  	}
   120  
   121  	updateStrategy := d.Get("update_strategy").(string)
   122  	if !(updateStrategy == "NONE" || updateStrategy == "RESTART") {
   123  		return fmt.Errorf("Update strategy must be \"NONE\" or \"RESTART\"")
   124  	}
   125  
   126  	log.Printf("[DEBUG] InstanceGroupManager insert request: %#v", manager)
   127  	op, err := config.clientCompute.InstanceGroupManagers.Insert(
   128  		config.Project, d.Get("zone").(string), manager).Do()
   129  	if err != nil {
   130  		return fmt.Errorf("Error creating InstanceGroupManager: %s", err)
   131  	}
   132  
   133  	// It probably maybe worked, so store the ID now
   134  	d.SetId(manager.Name)
   135  
   136  	// Wait for the operation to complete
   137  	err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Creating InstanceGroupManager")
   138  	if err != nil {
   139  		return err
   140  	}
   141  
   142  	return resourceComputeInstanceGroupManagerRead(d, meta)
   143  }
   144  
   145  func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interface{}) error {
   146  	config := meta.(*Config)
   147  
   148  	manager, err := config.clientCompute.InstanceGroupManagers.Get(
   149  		config.Project, d.Get("zone").(string), d.Id()).Do()
   150  	if err != nil {
   151  		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
   152  			log.Printf("[WARN] Removing Instance Group Manager %q because it's gone", d.Get("name").(string))
   153  			// The resource doesn't exist anymore
   154  			d.SetId("")
   155  
   156  			return nil
   157  		}
   158  
   159  		return fmt.Errorf("Error reading instance group manager: %s", err)
   160  	}
   161  
   162  	// Set computed fields
   163  	d.Set("fingerprint", manager.Fingerprint)
   164  	d.Set("instance_group", manager.InstanceGroup)
   165  	d.Set("target_size", manager.TargetSize)
   166  	d.Set("self_link", manager.SelfLink)
   167  
   168  	return nil
   169  }
   170  func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error {
   171  	config := meta.(*Config)
   172  
   173  	d.Partial(true)
   174  
   175  	// If target_pools changes then update
   176  	if d.HasChange("target_pools") {
   177  		var targetPools []string
   178  		if attr := d.Get("target_pools").(*schema.Set); attr.Len() > 0 {
   179  			for _, v := range attr.List() {
   180  				targetPools = append(targetPools, v.(string))
   181  			}
   182  		}
   183  
   184  		// Build the parameter
   185  		setTargetPools := &compute.InstanceGroupManagersSetTargetPoolsRequest{
   186  			Fingerprint: d.Get("fingerprint").(string),
   187  			TargetPools: targetPools,
   188  		}
   189  
   190  		op, err := config.clientCompute.InstanceGroupManagers.SetTargetPools(
   191  			config.Project, d.Get("zone").(string), d.Id(), setTargetPools).Do()
   192  		if err != nil {
   193  			return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
   194  		}
   195  
   196  		// Wait for the operation to complete
   197  		err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager")
   198  		if err != nil {
   199  			return err
   200  		}
   201  
   202  		d.SetPartial("target_pools")
   203  	}
   204  
   205  	// If instance_template changes then update
   206  	if d.HasChange("instance_template") {
   207  		// Build the parameter
   208  		setInstanceTemplate := &compute.InstanceGroupManagersSetInstanceTemplateRequest{
   209  			InstanceTemplate: d.Get("instance_template").(string),
   210  		}
   211  
   212  		op, err := config.clientCompute.InstanceGroupManagers.SetInstanceTemplate(
   213  			config.Project, d.Get("zone").(string), d.Id(), setInstanceTemplate).Do()
   214  		if err != nil {
   215  			return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
   216  		}
   217  
   218  		// Wait for the operation to complete
   219  		err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager")
   220  		if err != nil {
   221  			return err
   222  		}
   223  
   224  		if d.Get("update_strategy").(string) == "RESTART" {
   225  			managedInstances, err := config.clientCompute.InstanceGroupManagers.ListManagedInstances(
   226  				config.Project, d.Get("zone").(string), d.Id()).Do()
   227  
   228  			managedInstanceCount := len(managedInstances.ManagedInstances)
   229  			instances := make([]string, managedInstanceCount)
   230  			for i, v := range managedInstances.ManagedInstances {
   231  				instances[i] = v.Instance
   232  			}
   233  
   234  			recreateInstances := &compute.InstanceGroupManagersRecreateInstancesRequest{
   235  				Instances: instances,
   236  			}
   237  
   238  			op, err = config.clientCompute.InstanceGroupManagers.RecreateInstances(
   239  				config.Project, d.Get("zone").(string), d.Id(), recreateInstances).Do()
   240  
   241  			if err != nil {
   242  				return fmt.Errorf("Error restarting instance group managers instances: %s", err)
   243  			}
   244  
   245  			// Wait for the operation to complete
   246  			err = computeOperationWaitZoneTime(config, op, d.Get("zone").(string),
   247  				managedInstanceCount*4, "Restarting InstanceGroupManagers instances")
   248  			if err != nil {
   249  				return err
   250  			}
   251  		}
   252  
   253  		d.SetPartial("instance_template")
   254  	}
   255  
   256  	// If size changes trigger a resize
   257  	if d.HasChange("target_size") {
   258  		if v, ok := d.GetOk("target_size"); ok {
   259  			// Only do anything if the new size is set
   260  			target_size := int64(v.(int))
   261  
   262  			op, err := config.clientCompute.InstanceGroupManagers.Resize(
   263  				config.Project, d.Get("zone").(string), d.Id(), target_size).Do()
   264  			if err != nil {
   265  				return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
   266  			}
   267  
   268  			// Wait for the operation to complete
   269  			err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager")
   270  			if err != nil {
   271  				return err
   272  			}
   273  		}
   274  
   275  		d.SetPartial("target_size")
   276  	}
   277  
   278  	d.Partial(false)
   279  
   280  	return resourceComputeInstanceGroupManagerRead(d, meta)
   281  }
   282  
   283  func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta interface{}) error {
   284  	config := meta.(*Config)
   285  
   286  	zone := d.Get("zone").(string)
   287  	op, err := config.clientCompute.InstanceGroupManagers.Delete(config.Project, zone, d.Id()).Do()
   288  	if err != nil {
   289  		return fmt.Errorf("Error deleting instance group manager: %s", err)
   290  	}
   291  
   292  	currentSize := int64(d.Get("target_size").(int))
   293  
   294  	// Wait for the operation to complete
   295  	err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Deleting InstanceGroupManager")
   296  
   297  	for err != nil && currentSize > 0 {
   298  		if !strings.Contains(err.Error(), "timeout") {
   299  			return err
   300  		}
   301  
   302  		instanceGroup, err := config.clientCompute.InstanceGroups.Get(
   303  			config.Project, d.Get("zone").(string), d.Id()).Do()
   304  
   305  		if err != nil {
   306  			return fmt.Errorf("Error getting instance group size: %s", err)
   307  		}
   308  
   309  		if instanceGroup.Size >= currentSize {
   310  			return fmt.Errorf("Error, instance group isn't shrinking during delete")
   311  		}
   312  
   313  		log.Printf("[INFO] timeout occured, but instance group is shrinking (%d < %d)", instanceGroup.Size, currentSize)
   314  
   315  		currentSize = instanceGroup.Size
   316  
   317  		err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Deleting InstanceGroupManager")
   318  	}
   319  
   320  	d.SetId("")
   321  	return nil
   322  }