github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/builtin/providers/google/resource_compute_instance_template.go (about) 1 package google 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 8 "github.com/hashicorp/terraform/helper/resource" 9 "github.com/hashicorp/terraform/helper/schema" 10 "google.golang.org/api/compute/v1" 11 "google.golang.org/api/googleapi" 12 ) 13 14 func resourceComputeInstanceTemplate() *schema.Resource { 15 return &schema.Resource{ 16 Create: resourceComputeInstanceTemplateCreate, 17 Read: resourceComputeInstanceTemplateRead, 18 Delete: resourceComputeInstanceTemplateDelete, 19 Importer: &schema.ResourceImporter{ 20 State: schema.ImportStatePassthrough, 21 }, 22 23 Schema: map[string]*schema.Schema{ 24 "name": &schema.Schema{ 25 Type: schema.TypeString, 26 Optional: true, 27 Computed: true, 28 ForceNew: true, 29 ConflictsWith: []string{"name_prefix"}, 30 ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { 31 // https://cloud.google.com/compute/docs/reference/latest/instanceTemplates#resource 32 value := v.(string) 33 if len(value) > 63 { 34 errors = append(errors, fmt.Errorf( 35 "%q cannot be longer than 63 characters", k)) 36 } 37 return 38 }, 39 }, 40 41 "name_prefix": &schema.Schema{ 42 Type: schema.TypeString, 43 Optional: true, 44 ForceNew: true, 45 ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { 46 // https://cloud.google.com/compute/docs/reference/latest/instanceTemplates#resource 47 // uuid is 26 characters, limit the prefix to 37. 48 value := v.(string) 49 if len(value) > 37 { 50 errors = append(errors, fmt.Errorf( 51 "%q cannot be longer than 37 characters, name is limited to 63", k)) 52 } 53 return 54 }, 55 }, 56 "disk": &schema.Schema{ 57 Type: schema.TypeList, 58 Required: true, 59 ForceNew: true, 60 Elem: &schema.Resource{ 61 Schema: map[string]*schema.Schema{ 62 "auto_delete": &schema.Schema{ 63 Type: schema.TypeBool, 64 Optional: true, 65 Default: true, 66 ForceNew: true, 67 }, 68 69 "boot": &schema.Schema{ 70 Type: schema.TypeBool, 71 Optional: true, 72 ForceNew: true, 73 Computed: true, 74 }, 75 76 "device_name": &schema.Schema{ 77 Type: schema.TypeString, 78 Optional: true, 79 ForceNew: true, 80 }, 81 82 "disk_name": &schema.Schema{ 83 Type: schema.TypeString, 84 Optional: true, 85 ForceNew: true, 86 }, 87 88 "disk_size_gb": &schema.Schema{ 89 Type: schema.TypeInt, 90 Optional: true, 91 ForceNew: true, 92 }, 93 94 "disk_type": &schema.Schema{ 95 Type: schema.TypeString, 96 Optional: true, 97 ForceNew: true, 98 Computed: true, 99 }, 100 101 "source_image": &schema.Schema{ 102 Type: schema.TypeString, 103 Optional: true, 104 ForceNew: true, 105 }, 106 107 "interface": &schema.Schema{ 108 Type: schema.TypeString, 109 Optional: true, 110 ForceNew: true, 111 Computed: true, 112 }, 113 114 "mode": &schema.Schema{ 115 Type: schema.TypeString, 116 Optional: true, 117 ForceNew: true, 118 Computed: true, 119 }, 120 121 "source": &schema.Schema{ 122 Type: schema.TypeString, 123 Optional: true, 124 ForceNew: true, 125 }, 126 127 "type": &schema.Schema{ 128 Type: schema.TypeString, 129 Optional: true, 130 ForceNew: true, 131 Computed: true, 132 }, 133 }, 134 }, 135 }, 136 137 "machine_type": &schema.Schema{ 138 Type: schema.TypeString, 139 Required: true, 140 ForceNew: true, 141 }, 142 143 "automatic_restart": &schema.Schema{ 144 Type: schema.TypeBool, 145 Optional: true, 146 Default: true, 147 ForceNew: true, 148 Deprecated: "Please use `scheduling.automatic_restart` instead", 149 }, 150 151 "can_ip_forward": &schema.Schema{ 152 Type: schema.TypeBool, 153 Optional: true, 154 Default: false, 155 ForceNew: true, 156 }, 157 158 "description": &schema.Schema{ 159 Type: schema.TypeString, 160 Optional: true, 161 ForceNew: true, 162 }, 163 164 "instance_description": &schema.Schema{ 165 Type: schema.TypeString, 166 Optional: true, 167 ForceNew: true, 168 }, 169 170 "metadata": &schema.Schema{ 171 Type: schema.TypeMap, 172 Optional: true, 173 ForceNew: true, 174 }, 175 176 "metadata_startup_script": &schema.Schema{ 177 Type: schema.TypeString, 178 Optional: true, 179 ForceNew: true, 180 }, 181 182 "metadata_fingerprint": &schema.Schema{ 183 Type: schema.TypeString, 184 Computed: true, 185 }, 186 187 "network_interface": &schema.Schema{ 188 Type: schema.TypeList, 189 Optional: true, 190 ForceNew: true, 191 Elem: &schema.Resource{ 192 Schema: map[string]*schema.Schema{ 193 "network": &schema.Schema{ 194 Type: schema.TypeString, 195 Optional: true, 196 ForceNew: true, 197 Computed: true, 198 }, 199 200 "subnetwork": &schema.Schema{ 201 Type: schema.TypeString, 202 Optional: true, 203 ForceNew: true, 204 }, 205 206 "subnetwork_project": &schema.Schema{ 207 Type: schema.TypeString, 208 Optional: true, 209 ForceNew: true, 210 }, 211 212 "access_config": &schema.Schema{ 213 Type: schema.TypeList, 214 Optional: true, 215 Elem: &schema.Resource{ 216 Schema: map[string]*schema.Schema{ 217 "nat_ip": &schema.Schema{ 218 Type: schema.TypeString, 219 Computed: true, 220 Optional: true, 221 }, 222 }, 223 }, 224 }, 225 }, 226 }, 227 }, 228 229 "on_host_maintenance": &schema.Schema{ 230 Type: schema.TypeString, 231 Optional: true, 232 ForceNew: true, 233 Deprecated: "Please use `scheduling.on_host_maintenance` instead", 234 }, 235 236 "project": &schema.Schema{ 237 Type: schema.TypeString, 238 Optional: true, 239 ForceNew: true, 240 Computed: true, 241 }, 242 243 "region": &schema.Schema{ 244 Type: schema.TypeString, 245 Optional: true, 246 ForceNew: true, 247 }, 248 249 "scheduling": &schema.Schema{ 250 Type: schema.TypeList, 251 Optional: true, 252 Computed: true, 253 ForceNew: true, 254 Elem: &schema.Resource{ 255 Schema: map[string]*schema.Schema{ 256 "preemptible": &schema.Schema{ 257 Type: schema.TypeBool, 258 Optional: true, 259 Default: false, 260 ForceNew: true, 261 }, 262 263 "automatic_restart": &schema.Schema{ 264 Type: schema.TypeBool, 265 Optional: true, 266 Default: true, 267 ForceNew: true, 268 }, 269 270 "on_host_maintenance": &schema.Schema{ 271 Type: schema.TypeString, 272 Optional: true, 273 Computed: true, 274 ForceNew: true, 275 }, 276 }, 277 }, 278 }, 279 280 "self_link": &schema.Schema{ 281 Type: schema.TypeString, 282 Computed: true, 283 }, 284 285 "service_account": &schema.Schema{ 286 Type: schema.TypeList, 287 MaxItems: 1, 288 Optional: true, 289 ForceNew: true, 290 Elem: &schema.Resource{ 291 Schema: map[string]*schema.Schema{ 292 "email": &schema.Schema{ 293 Type: schema.TypeString, 294 Optional: true, 295 Computed: true, 296 ForceNew: true, 297 }, 298 299 "scopes": &schema.Schema{ 300 Type: schema.TypeList, 301 Required: true, 302 ForceNew: true, 303 Elem: &schema.Schema{ 304 Type: schema.TypeString, 305 StateFunc: func(v interface{}) string { 306 return canonicalizeServiceScope(v.(string)) 307 }, 308 }, 309 }, 310 }, 311 }, 312 }, 313 314 "tags": &schema.Schema{ 315 Type: schema.TypeSet, 316 Optional: true, 317 ForceNew: true, 318 Elem: &schema.Schema{Type: schema.TypeString}, 319 Set: schema.HashString, 320 }, 321 322 "tags_fingerprint": &schema.Schema{ 323 Type: schema.TypeString, 324 Computed: true, 325 }, 326 }, 327 } 328 } 329 330 func buildDisks(d *schema.ResourceData, meta interface{}) ([]*compute.AttachedDisk, error) { 331 config := meta.(*Config) 332 333 disksCount := d.Get("disk.#").(int) 334 335 disks := make([]*compute.AttachedDisk, 0, disksCount) 336 for i := 0; i < disksCount; i++ { 337 prefix := fmt.Sprintf("disk.%d", i) 338 339 // Build the disk 340 var disk compute.AttachedDisk 341 disk.Type = "PERSISTENT" 342 disk.Mode = "READ_WRITE" 343 disk.Interface = "SCSI" 344 disk.Boot = i == 0 345 disk.AutoDelete = d.Get(prefix + ".auto_delete").(bool) 346 347 if v, ok := d.GetOk(prefix + ".boot"); ok { 348 disk.Boot = v.(bool) 349 } 350 351 if v, ok := d.GetOk(prefix + ".device_name"); ok { 352 disk.DeviceName = v.(string) 353 } 354 355 if v, ok := d.GetOk(prefix + ".source"); ok { 356 disk.Source = v.(string) 357 } else { 358 disk.InitializeParams = &compute.AttachedDiskInitializeParams{} 359 360 if v, ok := d.GetOk(prefix + ".disk_name"); ok { 361 disk.InitializeParams.DiskName = v.(string) 362 } 363 if v, ok := d.GetOk(prefix + ".disk_size_gb"); ok { 364 disk.InitializeParams.DiskSizeGb = int64(v.(int)) 365 } 366 disk.InitializeParams.DiskType = "pd-standard" 367 if v, ok := d.GetOk(prefix + ".disk_type"); ok { 368 disk.InitializeParams.DiskType = v.(string) 369 } 370 371 if v, ok := d.GetOk(prefix + ".source_image"); ok { 372 imageName := v.(string) 373 imageUrl, err := resolveImage(config, imageName) 374 if err != nil { 375 return nil, fmt.Errorf( 376 "Error resolving image name '%s': %s", 377 imageName, err) 378 } 379 disk.InitializeParams.SourceImage = imageUrl 380 } 381 } 382 383 if v, ok := d.GetOk(prefix + ".interface"); ok { 384 disk.Interface = v.(string) 385 } 386 387 if v, ok := d.GetOk(prefix + ".mode"); ok { 388 disk.Mode = v.(string) 389 } 390 391 if v, ok := d.GetOk(prefix + ".type"); ok { 392 disk.Type = v.(string) 393 } 394 395 disks = append(disks, &disk) 396 } 397 398 return disks, nil 399 } 400 401 func buildNetworks(d *schema.ResourceData, meta interface{}) ([]*compute.NetworkInterface, error) { 402 // Build up the list of networks 403 config := meta.(*Config) 404 405 project, err := getProject(d, config) 406 if err != nil { 407 return nil, err 408 } 409 410 networksCount := d.Get("network_interface.#").(int) 411 networkInterfaces := make([]*compute.NetworkInterface, 0, networksCount) 412 for i := 0; i < networksCount; i++ { 413 prefix := fmt.Sprintf("network_interface.%d", i) 414 415 var networkName, subnetworkName, subnetworkProject string 416 if v, ok := d.GetOk(prefix + ".network"); ok { 417 networkName = v.(string) 418 } 419 if v, ok := d.GetOk(prefix + ".subnetwork"); ok { 420 subnetworkName = v.(string) 421 } 422 if v, ok := d.GetOk(prefix + ".subnetwork_project"); ok { 423 subnetworkProject = v.(string) 424 } 425 if networkName == "" && subnetworkName == "" { 426 return nil, fmt.Errorf("network or subnetwork must be provided") 427 } 428 if networkName != "" && subnetworkName != "" { 429 return nil, fmt.Errorf("network or subnetwork must not both be provided") 430 } 431 432 var networkLink, subnetworkLink string 433 if networkName != "" { 434 networkLink, err = getNetworkLink(d, config, prefix+".network") 435 if err != nil { 436 return nil, fmt.Errorf("Error referencing network '%s': %s", 437 networkName, err) 438 } 439 440 } else { 441 // lookup subnetwork link using region and subnetwork name 442 region, err := getRegion(d, config) 443 if err != nil { 444 return nil, err 445 } 446 if subnetworkProject == "" { 447 subnetworkProject = project 448 } 449 subnetwork, err := config.clientCompute.Subnetworks.Get( 450 subnetworkProject, region, subnetworkName).Do() 451 if err != nil { 452 return nil, fmt.Errorf( 453 "Error referencing subnetwork '%s' in region '%s': %s", 454 subnetworkName, region, err) 455 } 456 subnetworkLink = subnetwork.SelfLink 457 } 458 459 // Build the networkInterface 460 var iface compute.NetworkInterface 461 iface.Network = networkLink 462 iface.Subnetwork = subnetworkLink 463 464 accessConfigsCount := d.Get(prefix + ".access_config.#").(int) 465 iface.AccessConfigs = make([]*compute.AccessConfig, accessConfigsCount) 466 for j := 0; j < accessConfigsCount; j++ { 467 acPrefix := fmt.Sprintf("%s.access_config.%d", prefix, j) 468 iface.AccessConfigs[j] = &compute.AccessConfig{ 469 Type: "ONE_TO_ONE_NAT", 470 NatIP: d.Get(acPrefix + ".nat_ip").(string), 471 } 472 } 473 474 networkInterfaces = append(networkInterfaces, &iface) 475 } 476 return networkInterfaces, nil 477 } 478 479 func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interface{}) error { 480 config := meta.(*Config) 481 482 project, err := getProject(d, config) 483 if err != nil { 484 return err 485 } 486 487 instanceProperties := &compute.InstanceProperties{} 488 489 instanceProperties.CanIpForward = d.Get("can_ip_forward").(bool) 490 instanceProperties.Description = d.Get("instance_description").(string) 491 instanceProperties.MachineType = d.Get("machine_type").(string) 492 disks, err := buildDisks(d, meta) 493 if err != nil { 494 return err 495 } 496 instanceProperties.Disks = disks 497 498 metadata, err := resourceInstanceMetadata(d) 499 if err != nil { 500 return err 501 } 502 instanceProperties.Metadata = metadata 503 networks, err := buildNetworks(d, meta) 504 if err != nil { 505 return err 506 } 507 instanceProperties.NetworkInterfaces = networks 508 509 instanceProperties.Scheduling = &compute.Scheduling{} 510 instanceProperties.Scheduling.OnHostMaintenance = "MIGRATE" 511 512 // Depreciated fields 513 if v, ok := d.GetOk("automatic_restart"); ok { 514 instanceProperties.Scheduling.AutomaticRestart = v.(bool) 515 } 516 517 if v, ok := d.GetOk("on_host_maintenance"); ok { 518 instanceProperties.Scheduling.OnHostMaintenance = v.(string) 519 } 520 521 forceSendFieldsScheduling := make([]string, 0, 3) 522 var hasSendMaintenance bool 523 hasSendMaintenance = false 524 if v, ok := d.GetOk("scheduling"); ok { 525 _schedulings := v.([]interface{}) 526 if len(_schedulings) > 1 { 527 return fmt.Errorf("Error, at most one `scheduling` block can be defined") 528 } 529 _scheduling := _schedulings[0].(map[string]interface{}) 530 531 if vp, okp := _scheduling["automatic_restart"]; okp { 532 instanceProperties.Scheduling.AutomaticRestart = vp.(bool) 533 forceSendFieldsScheduling = append(forceSendFieldsScheduling, "AutomaticRestart") 534 } 535 536 if vp, okp := _scheduling["on_host_maintenance"]; okp { 537 instanceProperties.Scheduling.OnHostMaintenance = vp.(string) 538 forceSendFieldsScheduling = append(forceSendFieldsScheduling, "OnHostMaintenance") 539 hasSendMaintenance = true 540 } 541 542 if vp, okp := _scheduling["preemptible"]; okp { 543 instanceProperties.Scheduling.Preemptible = vp.(bool) 544 forceSendFieldsScheduling = append(forceSendFieldsScheduling, "Preemptible") 545 if vp.(bool) && !hasSendMaintenance { 546 instanceProperties.Scheduling.OnHostMaintenance = "TERMINATE" 547 forceSendFieldsScheduling = append(forceSendFieldsScheduling, "OnHostMaintenance") 548 } 549 } 550 } 551 instanceProperties.Scheduling.ForceSendFields = forceSendFieldsScheduling 552 553 serviceAccountsCount := d.Get("service_account.#").(int) 554 serviceAccounts := make([]*compute.ServiceAccount, 0, serviceAccountsCount) 555 for i := 0; i < serviceAccountsCount; i++ { 556 prefix := fmt.Sprintf("service_account.%d", i) 557 558 scopesCount := d.Get(prefix + ".scopes.#").(int) 559 scopes := make([]string, 0, scopesCount) 560 for j := 0; j < scopesCount; j++ { 561 scope := d.Get(fmt.Sprintf(prefix+".scopes.%d", j)).(string) 562 scopes = append(scopes, canonicalizeServiceScope(scope)) 563 } 564 565 email := "default" 566 if v := d.Get(prefix + ".email"); v != nil { 567 email = v.(string) 568 } 569 570 serviceAccount := &compute.ServiceAccount{ 571 Email: email, 572 Scopes: scopes, 573 } 574 575 serviceAccounts = append(serviceAccounts, serviceAccount) 576 } 577 instanceProperties.ServiceAccounts = serviceAccounts 578 579 instanceProperties.Tags = resourceInstanceTags(d) 580 581 var itName string 582 if v, ok := d.GetOk("name"); ok { 583 itName = v.(string) 584 } else if v, ok := d.GetOk("name_prefix"); ok { 585 itName = resource.PrefixedUniqueId(v.(string)) 586 } else { 587 itName = resource.UniqueId() 588 } 589 instanceTemplate := compute.InstanceTemplate{ 590 Description: d.Get("description").(string), 591 Properties: instanceProperties, 592 Name: itName, 593 } 594 595 op, err := config.clientCompute.InstanceTemplates.Insert( 596 project, &instanceTemplate).Do() 597 if err != nil { 598 return fmt.Errorf("Error creating instance: %s", err) 599 } 600 601 // Store the ID now 602 d.SetId(instanceTemplate.Name) 603 604 err = computeOperationWaitGlobal(config, op, project, "Creating Instance Template") 605 if err != nil { 606 return err 607 } 608 609 return resourceComputeInstanceTemplateRead(d, meta) 610 } 611 612 func flattenDisks(disks []*compute.AttachedDisk, d *schema.ResourceData) []map[string]interface{} { 613 result := make([]map[string]interface{}, 0, len(disks)) 614 for i, disk := range disks { 615 diskMap := make(map[string]interface{}) 616 if disk.InitializeParams != nil { 617 var source_img = fmt.Sprintf("disk.%d.source_image", i) 618 if d.Get(source_img) == nil || d.Get(source_img) == "" { 619 sourceImageUrl := strings.Split(disk.InitializeParams.SourceImage, "/") 620 diskMap["source_image"] = sourceImageUrl[len(sourceImageUrl)-1] 621 } else { 622 diskMap["source_image"] = d.Get(source_img) 623 } 624 diskMap["disk_type"] = disk.InitializeParams.DiskType 625 diskMap["disk_name"] = disk.InitializeParams.DiskName 626 diskMap["disk_size_gb"] = disk.InitializeParams.DiskSizeGb 627 } 628 diskMap["auto_delete"] = disk.AutoDelete 629 diskMap["boot"] = disk.Boot 630 diskMap["device_name"] = disk.DeviceName 631 diskMap["interface"] = disk.Interface 632 diskMap["source"] = disk.Source 633 diskMap["mode"] = disk.Mode 634 diskMap["type"] = disk.Type 635 result = append(result, diskMap) 636 } 637 return result 638 } 639 640 func flattenNetworkInterfaces(networkInterfaces []*compute.NetworkInterface) ([]map[string]interface{}, string) { 641 result := make([]map[string]interface{}, 0, len(networkInterfaces)) 642 region := "" 643 for _, networkInterface := range networkInterfaces { 644 networkInterfaceMap := make(map[string]interface{}) 645 if networkInterface.Network != "" { 646 networkUrl := strings.Split(networkInterface.Network, "/") 647 networkInterfaceMap["network"] = networkUrl[len(networkUrl)-1] 648 } 649 if networkInterface.Subnetwork != "" { 650 subnetworkUrl := strings.Split(networkInterface.Subnetwork, "/") 651 networkInterfaceMap["subnetwork"] = subnetworkUrl[len(subnetworkUrl)-1] 652 region = subnetworkUrl[len(subnetworkUrl)-3] 653 networkInterfaceMap["subnetwork_project"] = subnetworkUrl[len(subnetworkUrl)-5] 654 } 655 656 if networkInterface.AccessConfigs != nil { 657 accessConfigsMap := make([]map[string]interface{}, 0, len(networkInterface.AccessConfigs)) 658 for _, accessConfig := range networkInterface.AccessConfigs { 659 accessConfigMap := make(map[string]interface{}) 660 accessConfigMap["nat_ip"] = accessConfig.NatIP 661 662 accessConfigsMap = append(accessConfigsMap, accessConfigMap) 663 } 664 networkInterfaceMap["access_config"] = accessConfigsMap 665 } 666 result = append(result, networkInterfaceMap) 667 } 668 return result, region 669 } 670 671 func flattenScheduling(scheduling *compute.Scheduling) ([]map[string]interface{}, bool) { 672 result := make([]map[string]interface{}, 0, 1) 673 schedulingMap := make(map[string]interface{}) 674 schedulingMap["automatic_restart"] = scheduling.AutomaticRestart 675 schedulingMap["on_host_maintenance"] = scheduling.OnHostMaintenance 676 schedulingMap["preemptible"] = scheduling.Preemptible 677 result = append(result, schedulingMap) 678 return result, scheduling.AutomaticRestart 679 } 680 681 func flattenServiceAccounts(serviceAccounts []*compute.ServiceAccount) []map[string]interface{} { 682 result := make([]map[string]interface{}, 0, len(serviceAccounts)) 683 for _, serviceAccount := range serviceAccounts { 684 serviceAccountMap := make(map[string]interface{}) 685 serviceAccountMap["email"] = serviceAccount.Email 686 serviceAccountMap["scopes"] = serviceAccount.Scopes 687 688 result = append(result, serviceAccountMap) 689 } 690 return result 691 } 692 693 func flattenMetadata(metadata *compute.Metadata) map[string]string { 694 metadataMap := make(map[string]string) 695 for _, item := range metadata.Items { 696 metadataMap[item.Key] = *item.Value 697 } 698 return metadataMap 699 } 700 701 func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{}) error { 702 config := meta.(*Config) 703 project, err := getProject(d, config) 704 if err != nil { 705 return err 706 } 707 708 instanceTemplate, err := config.clientCompute.InstanceTemplates.Get( 709 project, d.Id()).Do() 710 if err != nil { 711 if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 { 712 log.Printf("[WARN] Removing Instance Template %q because it's gone", d.Get("name").(string)) 713 // The resource doesn't exist anymore 714 d.SetId("") 715 return nil 716 } 717 718 return fmt.Errorf("Error reading instance template: %s", err) 719 } 720 721 // Set the metadata fingerprint if there is one. 722 if instanceTemplate.Properties.Metadata != nil { 723 if err = d.Set("metadata_fingerprint", instanceTemplate.Properties.Metadata.Fingerprint); err != nil { 724 return fmt.Errorf("Error setting metadata_fingerprint: %s", err) 725 } 726 727 md := instanceTemplate.Properties.Metadata 728 729 _md := flattenMetadata(md) 730 731 if script, scriptExists := d.GetOk("metadata_startup_script"); scriptExists { 732 if err = d.Set("metadata_startup_script", script); err != nil { 733 return fmt.Errorf("Error setting metadata_startup_script: %s", err) 734 } 735 delete(_md, "startup-script") 736 } 737 if err = d.Set("metadata", _md); err != nil { 738 return fmt.Errorf("Error setting metadata: %s", err) 739 } 740 } 741 742 // Set the tags fingerprint if there is one. 743 if instanceTemplate.Properties.Tags != nil { 744 if err = d.Set("tags_fingerprint", instanceTemplate.Properties.Tags.Fingerprint); err != nil { 745 return fmt.Errorf("Error setting tags_fingerprint: %s", err) 746 } 747 } 748 if err = d.Set("self_link", instanceTemplate.SelfLink); err != nil { 749 return fmt.Errorf("Error setting self_link: %s", err) 750 } 751 if err = d.Set("name", instanceTemplate.Name); err != nil { 752 return fmt.Errorf("Error setting name: %s", err) 753 } 754 if instanceTemplate.Properties.Disks != nil { 755 if err = d.Set("disk", flattenDisks(instanceTemplate.Properties.Disks, d)); err != nil { 756 return fmt.Errorf("Error setting disk: %s", err) 757 } 758 } 759 if err = d.Set("description", instanceTemplate.Description); err != nil { 760 return fmt.Errorf("Error setting description: %s", err) 761 } 762 if err = d.Set("machine_type", instanceTemplate.Properties.MachineType); err != nil { 763 return fmt.Errorf("Error setting machine_type: %s", err) 764 } 765 766 if err = d.Set("can_ip_forward", instanceTemplate.Properties.CanIpForward); err != nil { 767 return fmt.Errorf("Error setting can_ip_forward: %s", err) 768 } 769 770 if err = d.Set("instance_description", instanceTemplate.Properties.Description); err != nil { 771 return fmt.Errorf("Error setting instance_description: %s", err) 772 } 773 if err = d.Set("project", project); err != nil { 774 return fmt.Errorf("Error setting project: %s", err) 775 } 776 if instanceTemplate.Properties.NetworkInterfaces != nil { 777 networkInterfaces, region := flattenNetworkInterfaces(instanceTemplate.Properties.NetworkInterfaces) 778 if err = d.Set("network_interface", networkInterfaces); err != nil { 779 return fmt.Errorf("Error setting network_interface: %s", err) 780 } 781 // region is where to look up the subnetwork if there is one attached to the instance template 782 if region != "" { 783 if err = d.Set("region", region); err != nil { 784 return fmt.Errorf("Error setting region: %s", err) 785 } 786 } 787 } 788 if instanceTemplate.Properties.Scheduling != nil { 789 scheduling, autoRestart := flattenScheduling(instanceTemplate.Properties.Scheduling) 790 if err = d.Set("scheduling", scheduling); err != nil { 791 return fmt.Errorf("Error setting scheduling: %s", err) 792 } 793 if err = d.Set("automatic_restart", autoRestart); err != nil { 794 return fmt.Errorf("Error setting automatic_restart: %s", err) 795 } 796 } 797 if instanceTemplate.Properties.Tags != nil { 798 if err = d.Set("tags", instanceTemplate.Properties.Tags.Items); err != nil { 799 return fmt.Errorf("Error setting tags: %s", err) 800 } 801 } 802 if instanceTemplate.Properties.ServiceAccounts != nil { 803 if err = d.Set("service_account", flattenServiceAccounts(instanceTemplate.Properties.ServiceAccounts)); err != nil { 804 return fmt.Errorf("Error setting service_account: %s", err) 805 } 806 } 807 return nil 808 } 809 810 func resourceComputeInstanceTemplateDelete(d *schema.ResourceData, meta interface{}) error { 811 config := meta.(*Config) 812 813 project, err := getProject(d, config) 814 if err != nil { 815 return err 816 } 817 818 op, err := config.clientCompute.InstanceTemplates.Delete( 819 project, d.Id()).Do() 820 if err != nil { 821 return fmt.Errorf("Error deleting instance template: %s", err) 822 } 823 824 err = computeOperationWaitGlobal(config, op, project, "Deleting Instance Template") 825 if err != nil { 826 return err 827 } 828 829 d.SetId("") 830 return nil 831 }