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 }