github.com/shvar/terraform@v0.6.9-0.20151215234924-3365cd2231df/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 // The resource doesn't exist anymore 153 d.SetId("") 154 155 return nil 156 } 157 158 return fmt.Errorf("Error reading instance group manager: %s", err) 159 } 160 161 // Set computed fields 162 d.Set("fingerprint", manager.Fingerprint) 163 d.Set("instance_group", manager.InstanceGroup) 164 d.Set("target_size", manager.TargetSize) 165 d.Set("self_link", manager.SelfLink) 166 167 return nil 168 } 169 func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error { 170 config := meta.(*Config) 171 172 d.Partial(true) 173 174 // If target_pools changes then update 175 if d.HasChange("target_pools") { 176 var targetPools []string 177 if attr := d.Get("target_pools").(*schema.Set); attr.Len() > 0 { 178 for _, v := range attr.List() { 179 targetPools = append(targetPools, v.(string)) 180 } 181 } 182 183 // Build the parameter 184 setTargetPools := &compute.InstanceGroupManagersSetTargetPoolsRequest{ 185 Fingerprint: d.Get("fingerprint").(string), 186 TargetPools: targetPools, 187 } 188 189 op, err := config.clientCompute.InstanceGroupManagers.SetTargetPools( 190 config.Project, d.Get("zone").(string), d.Id(), setTargetPools).Do() 191 if err != nil { 192 return fmt.Errorf("Error updating InstanceGroupManager: %s", err) 193 } 194 195 // Wait for the operation to complete 196 err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager") 197 if err != nil { 198 return err 199 } 200 201 d.SetPartial("target_pools") 202 } 203 204 // If instance_template changes then update 205 if d.HasChange("instance_template") { 206 // Build the parameter 207 setInstanceTemplate := &compute.InstanceGroupManagersSetInstanceTemplateRequest{ 208 InstanceTemplate: d.Get("instance_template").(string), 209 } 210 211 op, err := config.clientCompute.InstanceGroupManagers.SetInstanceTemplate( 212 config.Project, d.Get("zone").(string), d.Id(), setInstanceTemplate).Do() 213 if err != nil { 214 return fmt.Errorf("Error updating InstanceGroupManager: %s", err) 215 } 216 217 // Wait for the operation to complete 218 err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager") 219 if err != nil { 220 return err 221 } 222 223 if d.Get("update_strategy").(string) == "RESTART" { 224 managedInstances, err := config.clientCompute.InstanceGroupManagers.ListManagedInstances( 225 config.Project, d.Get("zone").(string), d.Id()).Do() 226 227 managedInstanceCount := len(managedInstances.ManagedInstances) 228 instances := make([]string, managedInstanceCount) 229 for i, v := range managedInstances.ManagedInstances { 230 instances[i] = v.Instance 231 } 232 233 recreateInstances := &compute.InstanceGroupManagersRecreateInstancesRequest{ 234 Instances: instances, 235 } 236 237 op, err = config.clientCompute.InstanceGroupManagers.RecreateInstances( 238 config.Project, d.Get("zone").(string), d.Id(), recreateInstances).Do() 239 240 if err != nil { 241 return fmt.Errorf("Error restarting instance group managers instances: %s", err) 242 } 243 244 // Wait for the operation to complete 245 err = computeOperationWaitZoneTime(config, op, d.Get("zone").(string), 246 managedInstanceCount * 4, "Restarting InstanceGroupManagers instances") 247 if err != nil { 248 return err 249 } 250 } 251 252 d.SetPartial("instance_template") 253 } 254 255 // If size changes trigger a resize 256 if d.HasChange("target_size") { 257 if v, ok := d.GetOk("target_size"); ok { 258 // Only do anything if the new size is set 259 target_size := int64(v.(int)) 260 261 op, err := config.clientCompute.InstanceGroupManagers.Resize( 262 config.Project, d.Get("zone").(string), d.Id(), target_size).Do() 263 if err != nil { 264 return fmt.Errorf("Error updating InstanceGroupManager: %s", err) 265 } 266 267 // Wait for the operation to complete 268 err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Updating InstanceGroupManager") 269 if err != nil { 270 return err 271 } 272 } 273 274 d.SetPartial("target_size") 275 } 276 277 d.Partial(false) 278 279 return resourceComputeInstanceGroupManagerRead(d, meta) 280 } 281 282 func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta interface{}) error { 283 config := meta.(*Config) 284 285 zone := d.Get("zone").(string) 286 op, err := config.clientCompute.InstanceGroupManagers.Delete(config.Project, zone, d.Id()).Do() 287 if err != nil { 288 return fmt.Errorf("Error deleting instance group manager: %s", err) 289 } 290 291 currentSize := int64(d.Get("target_size").(int)) 292 293 // Wait for the operation to complete 294 err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Deleting InstanceGroupManager") 295 296 for err != nil && currentSize > 0 { 297 if !strings.Contains(err.Error(), "timeout") { 298 return err 299 } 300 301 instanceGroup, err := config.clientCompute.InstanceGroups.Get( 302 config.Project, d.Get("zone").(string), d.Id()).Do() 303 304 if err != nil { 305 return fmt.Errorf("Error getting instance group size: %s", err) 306 } 307 308 if instanceGroup.Size >= currentSize { 309 return fmt.Errorf("Error, instance group isn't shrinking during delete") 310 } 311 312 log.Printf("[INFO] timeout occured, but instance group is shrinking (%d < %d)", instanceGroup.Size, currentSize) 313 314 currentSize = instanceGroup.Size 315 316 err = computeOperationWaitZone(config, op, d.Get("zone").(string), "Deleting InstanceGroupManager") 317 } 318 319 d.SetId("") 320 return nil 321 }