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