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