Skip to content

Commit 8daf949

Browse files
modular-magiciannat-henderson
authored andcommitted
fix disk behaivor in compute_instance_from_template (#2695)
1 parent 4a974b2 commit 8daf949

3 files changed

+368
-7
lines changed

google/provider.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ func Provider() terraform.ResourceProvider {
7272
"google_compute_forwarding_rule": dataSourceGoogleComputeForwardingRule(),
7373
"google_compute_image": dataSourceGoogleComputeImage(),
7474
"google_compute_instance": dataSourceGoogleComputeInstance(),
75-
"google_compute_instance_group": dataSourceGoogleComputeInstanceGroup(),
7675
"google_compute_global_address": dataSourceGoogleComputeGlobalAddress(),
76+
"google_compute_instance_group": dataSourceGoogleComputeInstanceGroup(),
7777
"google_compute_lb_ip_ranges": dataSourceGoogleComputeLbIpRanges(),
7878
"google_compute_network": dataSourceGoogleComputeNetwork(),
7979
"google_compute_regions": dataSourceGoogleComputeRegions(),

google/resource_compute_instance_from_template.go

+89-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66

77
"github.com/hashicorp/terraform/helper/schema"
88
strcase "github.com/stoewer/go-strcase"
9+
computeBeta "google.golang.org/api/compute/v0.beta"
10+
compute "google.golang.org/api/compute/v1"
911
)
1012

1113
func resourceComputeInstanceFromTemplate() *schema.Resource {
@@ -98,8 +100,26 @@ func resourceComputeInstanceFromTemplateCreate(d *schema.ResourceData, meta inte
98100
return err
99101
}
100102

101-
// Force send all top-level fields in case they're overridden to zero values.
103+
tpl, err := ParseInstanceTemplateFieldValue(d.Get("source_instance_template").(string), d, config)
104+
if err != nil {
105+
return err
106+
}
107+
108+
it, err := config.clientComputeBeta.InstanceTemplates.Get(project, tpl.Name).Do()
109+
if err != nil {
110+
return err
111+
}
112+
113+
instance.Disks, err = adjustInstanceFromTemplateDisks(d, config, it, zone, project)
114+
if err != nil {
115+
return err
116+
}
117+
118+
// Force send all top-level fields that have been set in case they're overridden to zero values.
102119
// TODO: consider doing so for nested fields as well.
120+
// Initialize ForceSendFields to empty so we don't get things that the instance resource
121+
// always force-sends.
122+
instance.ForceSendFields = []string{}
103123
for f, s := range computeInstanceFromTemplateSchema() {
104124
// It seems that GetOkExists always returns true for sets.
105125
// TODO: confirm this and file issue against Terraform core.
@@ -116,11 +136,6 @@ func resourceComputeInstanceFromTemplateCreate(d *schema.ResourceData, meta inte
116136
}
117137
}
118138

119-
tpl, err := ParseInstanceTemplateFieldValue(d.Get("source_instance_template").(string), d, config)
120-
if err != nil {
121-
return err
122-
}
123-
124139
log.Printf("[INFO] Requesting instance creation")
125140
op, err := config.clientComputeBeta.Instances.Insert(project, zone.Name, instance).SourceInstanceTemplate(tpl.RelativeLink()).Do()
126141
if err != nil {
@@ -140,3 +155,71 @@ func resourceComputeInstanceFromTemplateCreate(d *schema.ResourceData, meta inte
140155

141156
return resourceComputeInstanceRead(d, meta)
142157
}
158+
159+
// Instances have disks spread across multiple schema properties. This function
160+
// ensures that overriding one of these properties does not override the others.
161+
func adjustInstanceFromTemplateDisks(d *schema.ResourceData, config *Config, it *computeBeta.InstanceTemplate, zone *compute.Zone, project string) ([]*computeBeta.AttachedDisk, error) {
162+
disks := []*computeBeta.AttachedDisk{}
163+
if _, hasBootDisk := d.GetOk("boot_disk"); hasBootDisk {
164+
bootDisk, err := expandBootDisk(d, config, zone, project)
165+
if err != nil {
166+
return nil, err
167+
}
168+
disks = append(disks, bootDisk)
169+
} else {
170+
// boot disk was not overridden, so use the one from the instance template
171+
for _, disk := range it.Properties.Disks {
172+
if disk.Boot {
173+
if dt := disk.InitializeParams.DiskType; dt != "" {
174+
// Instances need a URL for the disk type, but instance templates
175+
// only have the name (since they're global).
176+
disk.InitializeParams.DiskType = fmt.Sprintf("zones/%s/diskTypes/%s", zone.Name, dt)
177+
}
178+
disks = append(disks, disk)
179+
break
180+
}
181+
}
182+
}
183+
184+
if _, hasScratchDisk := d.GetOk("scratch_disk"); hasScratchDisk {
185+
scratchDisks, err := expandScratchDisks(d, config, zone, project)
186+
if err != nil {
187+
return nil, err
188+
}
189+
disks = append(disks, scratchDisks...)
190+
} else {
191+
// scratch disks were not overridden, so use the ones from the instance template
192+
for _, disk := range it.Properties.Disks {
193+
if disk.Type == "SCRATCH" {
194+
disks = append(disks, disk)
195+
}
196+
}
197+
}
198+
199+
attachedDisksCount := d.Get("attached_disk.#").(int)
200+
if attachedDisksCount > 0 {
201+
for i := 0; i < attachedDisksCount; i++ {
202+
diskConfig := d.Get(fmt.Sprintf("attached_disk.%d", i)).(map[string]interface{})
203+
disk, err := expandAttachedDisk(diskConfig, d, config)
204+
if err != nil {
205+
return nil, err
206+
}
207+
208+
disks = append(disks, disk)
209+
}
210+
} else {
211+
// attached disks were not overridden, so use the ones from the instance template
212+
for _, disk := range it.Properties.Disks {
213+
if !disk.Boot && disk.Type != "SCRATCH" {
214+
if s := disk.Source; s != "" {
215+
// Instances need a URL for the disk source, but instance templates
216+
// only have the name (since they're global).
217+
disk.Source = fmt.Sprintf("zones/%s/disks/%s", zone.Name, s)
218+
}
219+
disks = append(disks, disk)
220+
}
221+
}
222+
}
223+
224+
return disks, nil
225+
}

0 commit comments

Comments
 (0)