Skip to content

Commit

Permalink
Add new region instance template resource (hashicorp#7507) (hashicorp…
Browse files Browse the repository at this point in the history
…#5370)

Signed-off-by: Modular Magician <[email protected]>
Co-authored-by: Jingcong Wang <[email protected]>
  • Loading branch information
modular-magician and Jingcong Wang authored Mar 27, 2023
1 parent 6a987a0 commit 324bd41
Show file tree
Hide file tree
Showing 7 changed files with 5,241 additions and 12 deletions.
6 changes: 6 additions & 0 deletions .changelog/7507.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```release-note:new-resource
`google_compute_region_instance_template`
```
```release-note:enhancement
compute: supported region instance template in`source_instance_template` field of `google_compute_instance_from_template` resource
```
1 change: 1 addition & 0 deletions google-beta/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1677,6 +1677,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) {
"google_compute_project_metadata": ResourceComputeProjectMetadata(),
"google_compute_project_metadata_item": ResourceComputeProjectMetadataItem(),
"google_compute_region_instance_group_manager": ResourceComputeRegionInstanceGroupManager(),
"google_compute_region_instance_template": ResourceComputeRegionInstanceTemplate(),
"google_compute_router_interface": ResourceComputeRouterInterface(),
"google_compute_security_policy": ResourceComputeSecurityPolicy(),
"google_compute_shared_vpc_host_project": ResourceComputeSharedVpcHostProject(),
Expand Down
67 changes: 55 additions & 12 deletions google-beta/resource_compute_instance_from_template.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package google

import (
"encoding/json"
"fmt"
"log"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

Expand Down Expand Up @@ -116,19 +118,60 @@ func resourceComputeInstanceFromTemplateCreate(d *schema.ResourceData, meta inte
return err
}

tpl, err := ParseInstanceTemplateFieldValue(d.Get("source_instance_template").(string), d, config)
if err != nil {
return err
}
sourceInstanceTemplate := d.Get("source_instance_template").(string)

it, err := config.NewComputeClient(userAgent).InstanceTemplates.Get(project, tpl.Name).Do()
tpl, err := ParseInstanceTemplateFieldValue(sourceInstanceTemplate, d, config)
if err != nil {
return err
}

instance.Disks, err = adjustInstanceFromTemplateDisks(d, config, it, zone, project)
if err != nil {
return err
it := compute.InstanceTemplate{}
var relativeUrl string

if strings.Contains(sourceInstanceTemplate, "global/instanceTemplates") {
instanceTemplate, err := config.NewComputeClient(userAgent).InstanceTemplates.Get(project, tpl.Name).Do()
if err != nil {
return err
}

it = *instanceTemplate
relativeUrl = tpl.RelativeLink()

instance.Disks, err = adjustInstanceFromTemplateDisks(d, config, &it, zone, project, false)
if err != nil {
return err
}
} else {
relativeUrl, err = replaceVars(d, config, "projects/{{project}}/regions/{{region}}/instanceTemplates/"+tpl.Name)
if err != nil {
return err
}

url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/instanceTemplates/"+tpl.Name)
if err != nil {
return err
}

instanceTemplate, err := SendRequest(config, "GET", project, url, userAgent, nil)
if err != nil {
return err
}

instancePropertiesObj, err := json.Marshal(instanceTemplate)
if err != nil {
fmt.Println(err)
return err
}

if err := json.Unmarshal(instancePropertiesObj, &it); err != nil {
fmt.Println(err)
return err
}

instance.Disks, err = adjustInstanceFromTemplateDisks(d, config, &it, zone, project, true)
if err != nil {
return err
}
}

// when we make the original call to expandComputeInstance expandScheduling is called, which sets default values.
Expand Down Expand Up @@ -158,7 +201,7 @@ func resourceComputeInstanceFromTemplateCreate(d *schema.ResourceData, meta inte
}

log.Printf("[INFO] Requesting instance creation")
op, err := config.NewComputeClient(userAgent).Instances.Insert(project, zone.Name, instance).SourceInstanceTemplate(tpl.RelativeLink()).Do()
op, err := config.NewComputeClient(userAgent).Instances.Insert(project, zone.Name, instance).SourceInstanceTemplate(relativeUrl).Do()
if err != nil {
return fmt.Errorf("Error creating instance: %s", err)
}
Expand All @@ -180,7 +223,7 @@ func resourceComputeInstanceFromTemplateCreate(d *schema.ResourceData, meta inte

// Instances have disks spread across multiple schema properties. This function
// ensures that overriding one of these properties does not override the others.
func adjustInstanceFromTemplateDisks(d *schema.ResourceData, config *Config, it *compute.InstanceTemplate, zone *compute.Zone, project string) ([]*compute.AttachedDisk, error) {
func adjustInstanceFromTemplateDisks(d *schema.ResourceData, config *Config, it *compute.InstanceTemplate, zone *compute.Zone, project string, isFromRegionalTemplate bool) ([]*compute.AttachedDisk, error) {
disks := []*compute.AttachedDisk{}
if _, hasBootDisk := d.GetOk("boot_disk"); hasBootDisk {
bootDisk, err := expandBootDisk(d, config, project)
Expand All @@ -192,7 +235,7 @@ func adjustInstanceFromTemplateDisks(d *schema.ResourceData, config *Config, it
// boot disk was not overridden, so use the one from the instance template
for _, disk := range it.Properties.Disks {
if disk.Boot {
if disk.Source != "" {
if disk.Source != "" && !isFromRegionalTemplate {
// Instances need a URL for the disk, but instance templates only have the name
disk.Source = fmt.Sprintf("projects/%s/zones/%s/disks/%s", project, zone.Name, disk.Source)
}
Expand Down Expand Up @@ -246,7 +289,7 @@ func adjustInstanceFromTemplateDisks(d *schema.ResourceData, config *Config, it
// attached disks were not overridden, so use the ones from the instance template
for _, disk := range it.Properties.Disks {
if !disk.Boot && disk.Type != "SCRATCH" {
if s := disk.Source; s != "" {
if s := disk.Source; s != "" && !isFromRegionalTemplate {
// Instances need a URL for the disk source, but instance templates
// only have the name (since they're global).
disk.Source = fmt.Sprintf("zones/%s/disks/%s", zone.Name, s)
Expand Down
103 changes: 103 additions & 0 deletions google-beta/resource_compute_instance_from_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,34 @@ func TestAccComputeInstanceFromTemplate_basic(t *testing.T) {
})
}

func TestAccComputeInstanceFromRegionTemplate_basic(t *testing.T) {
t.Parallel()

var instance compute.Instance
instanceName := fmt.Sprintf("tf-test-%s", RandString(t, 10))
templateName := fmt.Sprintf("tf-test-%s", RandString(t, 10))
resourceName := "google_compute_instance_from_template.foobar"

VcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: TestAccProviders,
CheckDestroy: testAccCheckComputeInstanceFromTemplateDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeInstanceFromRegionTemplate_basic(instanceName, templateName),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceExists(t, resourceName, &instance),

// Check that fields were set based on the template
resource.TestCheckResourceAttr(resourceName, "machine_type", "n1-standard-1"),
resource.TestCheckResourceAttr(resourceName, "attached_disk.#", "1"),
resource.TestCheckResourceAttr(resourceName, "scheduling.0.automatic_restart", "false"),
),
},
},
})
}

func TestAccComputeInstanceFromTemplate_overrideBootDisk(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -310,6 +338,81 @@ resource "google_compute_instance_from_template" "foobar" {
`, template, template, instance)
}

func testAccComputeInstanceFromRegionTemplate_basic(instance, template string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-11"
project = "debian-cloud"
}
resource "google_compute_region_disk" "foobar" {
name = "%s"
size = 10
type = "pd-ssd"
region = "us-central1"
replica_zones = ["us-central1-a", "us-central1-f"]
}
resource "google_compute_region_instance_template" "foobar" {
name = "%s"
region = "us-central1"
machine_type = "n1-standard-1" // can't be e2 because of local-ssd
disk {
source_image = data.google_compute_image.my_image.self_link
auto_delete = true
disk_size_gb = 100
boot = true
disk_type = "pd-ssd"
type = "PERSISTENT"
}
disk {
source = google_compute_region_disk.foobar.self_link
auto_delete = false
boot = false
}
disk {
disk_type = "local-ssd"
type = "SCRATCH"
interface = "NVME"
disk_size_gb = 375
}
network_interface {
network = "default"
}
metadata = {
foo = "bar"
}
scheduling {
automatic_restart = true
}
can_ip_forward = true
}
resource "google_compute_instance_from_template" "foobar" {
name = "%s"
zone = "us-central1-a"
source_instance_template = google_compute_region_instance_template.foobar.id
// Overrides
can_ip_forward = false
labels = {
my_key = "my_value"
}
scheduling {
automatic_restart = false
}
}
`, template, template, instance)
}

func testAccComputeInstanceFromTemplate_overrideBootDisk(templateDisk, overrideDisk, template, instance string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
Expand Down
Loading

0 comments on commit 324bd41

Please sign in to comment.